Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display UIActivityViewController as form sheet on iPad

I'm trying to display a share sheet without using a popover, ie no source view, or arrow.

Here's my code, starting from a base, single view app:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBAction func didTapShare(_ sender: UIButton) {
        let activity = UIActivityViewController(activityItems: ["banana"], applicationActivities: nil)
        
        if UIDevice.current.userInterfaceIdiom == .pad {
            activity.modalPresentationStyle = .formSheet
//            activity.preferredContentSize = CGSize(width: 400, height: 400)
        }
        
        present(activity, animated: true, completion: nil)
    }
    
}

This is of course crashing

"UIPopoverPresentationController (<UIPopoverPresentationController: 0x7fce07507900>) should have a non-nil sourceView or barButtonItem set before the presentation occurs."

But I don't want it to look like a popup, or have an arrow -- I want it to appear as a form sheet, in the middle of the screen.

Here's how it look in the Photos app:

Photos form sheet

like image 892
Lescai Ionel Avatar asked Dec 07 '25 15:12

Lescai Ionel


1 Answers

If you don't want to display UIActivityViewController as popover but rather as formSheet or pageSheet, you can just create your own view controller with UIActivityViewController as its child.

class ShareSheetController: UIViewController {

    private let activityController: UIActivityViewController

    init(items: [Any]) {
        self.activityController = UIActivityViewController(activityItems: items, applicationActivities: nil)
    
        super.init(nibName: nil, bundle: nil)
    
        modalPresentationStyle = .formSheet // or pageSheet
    }

    required init?(coder: NSCoder) {
        fatalError()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    
        addChild(activityController)
        view.addSubview(activityController.view)

        activityController.view.translatesAutoresizingMaskIntoConstraints = false
    
        NSLayoutConstraint.activate([
            activityController.view.topAnchor.constraint(equalTo: view.topAnchor),
            activityController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            activityController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            activityController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        ])
    }

}

Then you can present the ShareSheetController just like any other view controller.

let shareController = ShareSheetController(items: ["some_text"])
present(shareController, animated: true)
like image 157
Lukáš B. Avatar answered Dec 10 '25 04:12

Lukáš B.