objective c - UIActivityViewController crashing on iOS 8 iPads

ID : 10264

viewed : 14

Tags : iosobjective-cswiftuiactivityviewcontrollerios

Top 5 Answer for objective c - UIActivityViewController crashing on iOS 8 iPads

vote vote

95

On iPad the activity view controller will be displayed as a popover using the new UIPopoverPresentationController, it requires that you specify an anchor point for the presentation of the popover using one of the three following properties:

In order to specify the anchor point you will need to obtain a reference to the UIActivityController's UIPopoverPresentationController and set one of the properties as follows:

if ( [activityViewController respondsToSelector:@selector(popoverPresentationController)] ) {  // iOS8  activityViewController.popoverPresentationController.sourceView = parentView;  } 
vote vote

88

Same problem is come to my project then i found the solution that to open the UIActivityViewController in iPad we have to use UIPopoverController

Here is a code to use it in iPhone and iPad both:

//to attach the image and text with sharing  UIImage *image=[UIImage imageNamed:@"giraffe.png"]; NSString *str=@"Image form My app"; NSArray *postItems=@[str,image];  UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:postItems applicationActivities:nil];  //if iPhone if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {     [self presentViewController:controller animated:YES completion:nil]; } //if iPad else {     // Change Rect to position Popover     UIPopoverController *popup = [[UIPopoverController alloc] initWithContentViewController:controller];     [popup presentPopoverFromRect:CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height/4, 0, 0)inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } 

For swift 4.2 / swift 5

func openShareDilog() {     let text = "share text will goes here"      // set up activity view controller     let textToShare = [text]     let activityViewController = UIActivityViewController(activityItems: textToShare, applicationActivities: nil)     activityViewController.excludedActivityTypes = [.airDrop]      if let popoverController = activityViewController.popoverPresentationController {         popoverController.sourceRect = CGRect(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height / 2, width: 0, height: 0)         popoverController.sourceView = self.view         popoverController.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)     }      self.present(activityViewController, animated: true, completion: nil) } 
vote vote

77

I was encountering this exact problem recently (the original question) in Swift 2.0, where UIActivityViewController worked fine for iPhones, but caused crashes when simulating iPads.

I just want to add to this thread of answers here that, at least in Swift 2.0, you don't need an if statement. You can just make the popoverPresentationController optional.

As a quick aside, the accepted answer appears to be saying that you could have just a sourceView, just a sourceRect, or just a barButtonItem, but according to Apple's documentation for UIPopoverPresentationController you need one of the following:

  • barButtonItem
  • sourceView and sourceRect

The particular example I was working on is below, where I am creating a function that takes in a UIView (for the sourceView and sourceRect) and String (the UIActivityViewController's sole activityItem).

func presentActivityViewController(sourceView: UIView, activityItem: String ) {      let activityViewController = UIActivityViewController(activityItems: [activityItem], applicationActivities: [])      activityViewController.popoverPresentationController?.sourceView = sourceView     activityViewController.popoverPresentationController?.sourceRect = sourceView.bounds      self.presentViewController(activityViewController, animated: true, completion: nil) } 

This code works on iPhone and iPad (and even tvOS I think) -- if the device does not support popoverPresentationController, the two lines of code that mention it are essentially ignored.

Kinda nice that all you need to do to make it work for iPads is just add two lines of code, or just one if you're using a barButtonItem!

vote vote

66

I see a lot of people hardcoding iPhone/iPad etc. while using Swift code.

This is not needed, you have to use the language features. The following code assumes you will use a UIBarButtonItem and will work on both iPhone and iPad.

@IBAction func share(sender: AnyObject) {     let vc = UIActivityViewController(activityItems: ["hello"], applicationActivities: nil)     vc.popoverPresentationController?.barButtonItem = sender as? UIBarButtonItem     self.presentViewController(vc, animated: true, completion: nil)  } 

Notice how there are no If statements or any other crazy thing. The optional unwrapping will be nil on iPhone, so the line vc.popoverPresentationController? will not do anything on iPhones.

vote vote

54

Solution using Xamarin.iOS.

In my example I'm doing a screen capture, producing an image, and allowing the user to share the image. The pop up on the iPad is placed about in the middle of the screen.

var activityItems = new NSObject[] { image }; var excludedActivityTypes = new NSString[] {     UIActivityType.PostToWeibo,     UIActivityType.CopyToPasteboard,     UIActivityType.AddToReadingList,     UIActivityType.AssignToContact,     UIActivityType.Print, }; var activityViewController = new UIActivityViewController(activityItems, null);  //set subject line if email is used var subject = new NSString("subject"); activityViewController.SetValueForKey(NSObject.FromObject("Goal Length"), subject);  activityViewController.ExcludedActivityTypes = excludedActivityTypes; //configure for iPad, note if you do not your app will not pass app store review if(null != activityViewController.PopoverPresentationController) {     activityViewController.PopoverPresentationController.SourceView = this.View;     var frame = UIScreen.MainScreen.Bounds;     frame.Height /= 2;     activityViewController.PopoverPresentationController.SourceRect = frame; } this.PresentViewController(activityViewController, true, null); 

Top 3 video Explaining objective c - UIActivityViewController crashing on iOS 8 iPads

Related QUESTION?