我目前正在用Xcode 6 (Beta 6)测试我的应用程序。UIActivityViewController在iPhone设备和模拟器上工作得很好,但在iPad模拟器和设备(iOS 8)上崩溃

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

我使用以下代码用于iPhone和iPad的iOS 7以及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];

我得到一个类似的崩溃在我的另一个应用程序以及。你能引导我吗?ios8中的UIActivityViewController有什么变化吗?我查过了,但在这上面什么也没找到


当前回答

我看到很多人在使用Swift代码时对iPhone/iPad等进行硬编码。

这是不需要的,你必须使用语言功能。下面的代码假设你将使用一个UIBarButtonItem,并将在iPhone和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)
 }

注意这里没有If语句或其他疯狂的东西。可选的展开在iPhone上将是nil,所以行vc。popoverpresentationcontroller ?在iphone上没有任何功能。

其他回答

只是作为参考。

我分享以下代码,这一个使用Swift 5.0。此外,它还避免了弃用的窗口。

UIApplication.shared.windows.first ? .rootViewController !。present(actiycontroller, animated: true, completion: nil)

代码片段如下:

let activityController = UIActivityViewController(activityItems: [activityItem], applicationActivities: nil)

let scenes = UIApplication.shared.connectedScenes 
let windowScene = scenes.first as? UIWindowScene 
let window = windowScene?.windows.first 

if UIDevice.current.userInterfaceIdiom == .pad{
    activityController.popoverPresentationController?.sourceView = window
    activityController.popoverPresentationController?.sourceRect = CGRect(x:  UIScreen.main.bounds.width / 3, y:  UIScreen.main.bounds.height / 1.5, width: 400, height: 400)
}

window?.rootViewController!.present(activityController, animated: true)

它已经在iPhone和iPad上进行了测试。

希望它能帮助到一些人。

干杯!

在iPad上,活动视图控制器将显示为一个弹出窗口使用新的UIPopoverPresentationController,它要求你指定一个锚点为弹出窗口的表示使用以下三个属性之一:

栏按钮项 源视图 源矩形

为了指定锚点,你需要获得UIActivityController的UIPopoverPresentationController的引用,并设置其中一个属性如下所示:

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

我最近在Swift 2.0中遇到了这个确切的问题(最初的问题),其中UIActivityViewController在iphone上工作得很好,但在模拟ipad时导致了崩溃。

我只是想在这里补充一点,至少在Swift 2.0中,你不需要if语句。你可以让popoverPresentationController是可选的。

作为一个快速题外话,接受的答案似乎是说,你可以只有一个sourceView,只是一个sourceRect,或只是一个barButtonItem,但根据苹果的文档UIPopoverPresentationController你需要以下之一:

栏按钮项 源视图和源矩形

我正在工作的特定示例如下,在那里我创建了一个函数,接受一个UIView(为sourceView和sourceRect)和字符串(UIActivityViewController的唯一的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)
}

这段代码适用于iPhone和iPad(我认为甚至是tvOS)——如果设备不支持popoverPresentationController,那么提到它的两行代码基本上会被忽略。

有点好,所有你需要做的,使它工作的ipad只是添加两行代码,或者只是一个如果你使用barButtonItem!

解决Objective-C和使用UIPopoverPresentationController

    UIActivityViewController *controller = /*Init your Controller*/;
    //if iPhone
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
        [self presentViewController:controller animated:YES completion:nil];
    }
    //if iPad
    else {
        UIPopoverPresentationController* popOver = controller.popoverPresentationController
        if(popOver){
            popOver.sourceView = controller.view;
            popOver.sourceRect = CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height/4, 0, 0);
            [self presentViewController:controller animated:YES completion:nil];
        }
    }

我找到了这个解 首先,你呈现弹窗的视图控制器应该实现<UIPopoverPresentationControllerDelegate>协议。

接下来,你需要设置popoverPresentationController的委托。

添加以下功能:

- (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;
}