UIActivityViewController che si blocca su iOS 8 iPad


Answers

Lo stesso problema è arrivato al mio progetto quindi ho trovato la soluzione che per aprire UIActivityViewController in iPad dobbiamo usare UIPopoverController

Ecco un codice per usarlo in iPhone e iPad entrambi

//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];
}

Per il rapido 3

let imageURL: URL = URL(string: product.images[0].fullImageUrlString)!
let objectsToShare: [AnyObject] = [imageURL as AnyObject]
let activityViewController = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = self.view
activityViewController.excludedActivityTypes = [ UIActivityType.airDrop]
self.present(activityViewController, animated: true, completion: nil)
Question

Attualmente sto testando la mia app con Xcode 6 (Beta 6). UIActivityViewController funziona perfettamente con dispositivi e simulatori iPhone ma si blocca con simulatori e dispositivi iPad (iOS 8) con i seguenti registri

Terminating app due to uncaught exception 'NSGenericException', reason: 'UIPopoverPresentationController (<_UIAlertControllerActionSheetRegularPresentationController: 0x7fc7a874bd90>) should have a non-nil sourceView or barButtonItem set before the presentation occurs.'

Sto usando il seguente codice per iPhone e iPad sia per iOS 7 che per iOS 8

NSData *myData = [NSData dataWithContentsOfFile:_filename];
NSArray *activityItems = [NSArray arrayWithObjects:myData, nil];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:nil applicationActivities:nil];
activityViewController.excludedActivityTypes = @[UIActivityTypeCopyToPasteboard];
[self presentViewController:activityViewController animated:YES completion:nil];

Sto ottenendo un crash simile anche in una delle mie altre app. Puoi per favore guidarmi? qualcosa è cambiato con UIActivityViewController in iOS 8? Ho controllato ma non ho trovato nulla su questo




Swift, iOS 9/10 (dopo UIPopoverController deprecato)

let activityViewController = UIActivityViewController(activityItems: sharingItems, applicationActivities: nil)

    if UIDevice.currentDevice().userInterfaceIdiom == .Pad {

       if activityViewController.respondsToSelector(Selector("popoverPresentationController")) {
          activityViewController.popoverPresentationController?.sourceView = self.view
        }
    }

    self.presentViewController(activityViewController, animated: true, completion: nil)



Vedo un sacco di persone che codificano l'iPhone / iPad ecc. Mentre usano il codice Swift.

Questo non è necessario, devi usare le caratteristiche del linguaggio. Il seguente codice presuppone che userete un UIBarButtonItem e funzionerà sia su iPhone che su 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)
 }

Nota come non ci sono dichiarazioni If o altre cose pazze. Lo unwrapping opzionale sarà nullo su iPhone, quindi la riga vc.popoverPresentationController? non farà nulla sugli iPhone.




Ho trovato questa soluzione In primo luogo, il controller di visualizzazione che presenta il popover dovrebbe implementare il protocollo <UIPopoverPresentationControllerDelegate> .

Successivamente, dovrai impostare il delegato di popoverPresentationController .

Aggiungi queste funzioni:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Assuming you've hooked this all up in a Storyboard with a popover presentation style
    if ([segue.identifier isEqualToString:@"showPopover"]) {
        UINavigationController *destNav = segue.destinationViewController;
        PopoverContentsViewController *vc = destNav.viewControllers.firstObject;

        // This is the important part
        UIPopoverPresentationController *popPC = destNav.popoverPresentationController;
        popPC.delegate = self;
    }
}

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController: (UIPresentationController *)controller {
    return UIModalPresentationNone;
}



Correzione per Swift 2.0

    if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.Phone {
        self.presentViewController(activityVC, animated: true, completion: nil)
    }
    else {
        let popup: UIPopoverController = UIPopoverController(contentViewController: activityVC)
        popup.presentPopoverFromRect(CGRectMake(self.view.frame.size.width / 2, self.view.frame.size.height / 4, 0, 0), inView: self.view, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
    }



Swift 3:

class func openShareActions(image: UIImage, vc: UIViewController) {
    let activityVC = UIActivityViewController(activityItems: [image], applicationActivities: nil)
    if UIDevice.current.userInterfaceIdiom == .pad {
        if activityVC.responds(to: #selector(getter: UIViewController.popoverPresentationController)) {
            activityVC.popoverPresentationController?.sourceView = vc.view
        }
    }
    vc.present(activityVC, animated: true, completion: nil)
}



Per Swift 2.0. Ho scoperto che funziona se stai cercando di ancorare il popover a un pulsante di condivisione su iPad. Ciò presuppone che tu abbia creato uno sbocco per il pulsante di condivisione nella barra degli strumenti.

func share(sender: AnyObject) {
    let firstActivityItem = "test"

    let activityViewController = UIActivityViewController(activityItems: [firstActivityItem], applicationActivities: nil)

    if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.Phone {
        self.presentViewController(activityViewController, animated: true, completion: nil)
    }
    else {            
        if activityViewController.respondsToSelector("popoverPresentationController") {
            activityViewController.popoverPresentationController!.barButtonItem = sender as? UIBarButtonItem
            self.presentViewController(activityViewController, animated: true, completion: nil)
        }

    }
}



Links