'UIActivityViewController on iPad
I have been using the code below to show a UIActivityViewController
which worked fine when I was using Xcode 6, Swift 1.2 and iOS 8. However when I updated it shows the UIActivityViewController
but it is completely blank without any of the sharing options. Do you have any suggestions?
if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
let textToShare = textViewOne.text
let objectsToShare = [textToShare]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
let nav = UINavigationController(rootViewController: activityVC)
nav.modalPresentationStyle = UIModalPresentationStyle.Popover
let popover = nav.popoverPresentationController as UIPopoverPresentationController!
popover.sourceView = self.view
popover.sourceRect = sender.frame
self.presentViewController(nav, animated: true, completion: nil)
} else {
let textToShare = textViewOne.text
let objectsToShare = [textToShare]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
self.presentViewController(activityVC, animated: true, completion: nil)
}
Solution 1:[1]
This has fixed it.
let objectsToShare = [textToShare]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityVC.title = "Share One"
activityVC.excludedActivityTypes = []
activityVC.popoverPresentationController?.sourceView = self.view
activityVC.popoverPresentationController?.sourceRect = sender.frame
self.presentViewController(activityVC, animated: true, completion: nil)
in swift 3.0:
let objectsToShare = [textToShare]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityVC.title = "Share One"
activityVC.excludedActivityTypes = []
activityVC.popoverPresentationController?.sourceView = self.view
activityVC.popoverPresentationController?.sourceRect = sender.frame
self.present(activityVC, animated: true, completion: nil)
Solution 2:[2]
I was struggling with the above suggestion with SWIFT 5 since:
activity.popoverPresentationController?.sourceRect = sender.frame
does NOT WORK in some cases, since sender is not available in scope. Try instead to set with a CGRECT, something like:
activityController.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY,width: 0,height: 0)
I hope this helps some people.
Solution 3:[3]
Swift 4.0
let shareText = "Hi"
let activity = UIActivityViewController(activityItems: shareText, applicationActivities: nil)
activity.excludedActivityTypes = []
if UIDevice.current.userInterfaceIdiom == .pad {
activity.popoverPresentationController?.sourceView = self.view
activity.popoverPresentationController?.sourceRect = sender.frame
}
self.present(activity, animated: true, completion: nil)
Solution 4:[4]
I had sort of a different issue. I wanted the UIActivityViewController
to stay in the center of the screen but when rotating the iPad it was off centered when in Landscape.
Landscape wrong:
The 2 fixes was to make the UIActivityViewController a class property and most importantly set its sourceRect
in viewDidLayoutSubviews
. Follow the 5 steps-
// 1. make the activityVC a class property
var activityVC: UIActivityViewController?
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if UIDevice.current.userInterfaceIdiom == .pad {
// 2. set its sourceRect here. It's the same as in step 4
activityVC?.popoverPresentationController?.sourceRect = CGRect(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height / 2, width: 0, height: 0)
}
}
// 3. present the UIActivityViewController
func presentActivityVC() {
let objectsToShare = [textToShare]
activityVC = nil
activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityVC?.excludedActivityTypes = [.addToReadingList, .openInIBooks, .print]
activityVC?.popoverPresentationController?.sourceView = self.view
if UIDevice.current.userInterfaceIdiom == .phone {
activityVC?.modalPresentationStyle = .overFullScreen
}
if UIDevice.current.userInterfaceIdiom == .pad {
// 4. set its sourceRect here. It's the same as in step 2
activityVC?.popoverPresentationController?.sourceRect = CGRect(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height / 2, width: 0, height: 0)
activityVC?.popoverPresentationController?.permittedArrowDirections = []
}
present(activityVC!, animated: true, completion: nil)
activityVC?.completionWithItemsHandler = { [weak self](activityType, completed:Bool, returnedItems:[Any]?, error: Error?) in
if let error = error {
print(error.localizedDescription)
return
}
// 5. set the activityVC to nil after the user is done
DispatchQueue.main.async { [weak self] in
self?.activityVC = nil
}
}
}
Now when rotating it's centered both in landscape and portrait.
Landscape correct:
Portrait:
Solution 5:[5]
best solve for iPad and iPhone try it
let urlstring = "https://apps.apple.com/ae/app/"
let text = "some text for your app"
let url = NSURL(string: urlstring)
let textToShare = [url!,text] as [Any]
let activityViewController = UIActivityViewController(activityItems: textToShare as [Any], applicationActivities: nil)
activityViewController.excludedActivityTypes = [ UIActivity.ActivityType.airDrop, UIActivity.ActivityType.postToFacebook ,UIActivity.ActivityType.postToFlickr,UIActivity.ActivityType.postToTwitter,UIActivity.ActivityType.postToVimeo,UIActivity.ActivityType.mail,UIActivity.ActivityType.addToReadingList]
activityViewController.popoverPresentationController?.sourceView = self.view
activityViewController.popoverPresentationController?.sourceRect = view.bounds
activityViewController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.down
UIApplication.shared.windows.first?.rootViewController?.present(activityViewController, animated: true, completion: nil)
Solution 6:[6]
if you want to attach the popover to the sender view's bounds, then the following code will work:
let vc = UIActivityViewController(activityItems: [url], applicationActivities: nil)
if UIDevice.current.userInterfaceIdiom == .pad {
vc.popoverPresentationController?.sourceView = sender
vc.popoverPresentationController?.sourceRect = CGRect(origin: CGPoint.zero, size: sender.frame.size)
}
sourceRect
is defined in the coordinate space of the sourceView
, thus we need to specify the origin of the sourceRect
as CGPoint.zero
rather than sender.frame.origin
.
Solution 7:[7]
We would need to set the sourceView and sourceRect both specially for iPad.
We may try below snippet
activityViewController.popoverPresentationController?.sourceView = sender.self
activityViewController.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.minX + sender.frame.width/2, y: self.view.bounds.minY, width: 0, height: 0)
activityViewController.popoverPresentationController?.permittedArrowDirections = []
It would set the sourceView as sender's and sourceRect at center to the UI.
We are adding sender.frame.width/2
to x
coordinate and removing the anchor arrow as well to get the pop-up exactly at center.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Subhash Khimani |
Solution 2 | Donovan Marsh |
Solution 3 | Aayushi |
Solution 4 | |
Solution 5 | islam XDeveloper |
Solution 6 | Madiyar |
Solution 7 | Maverick |