UIActivityViewController在iOS 8的iPad上崩溃

309

我目前正在使用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];

我在我的另一个应用程序中也遇到了类似的崩溃。您能否指导我?iOS 8中的UIActivityViewController是否有任何更改?我已经检查过,但没有发现任何更改。


以下是关于编程的内容,请将其翻译为中文。请仅返回已翻译的文本:答案下面测试短语的成语。您应该使用@Galen的答案,它不会。 - doozMen
21个回答

5

使用UIPopoverPresentationController解决Objective-C相关问题

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

4

修正 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)
    }

2
UIPopoverController已被弃用。 - LevinsonTechnologies
1
谢谢!它帮了我很多。 - Oscar Falmer

4

仅供参考。

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

UIApplication.shared.windows.first?.rootViewController!.present(activityController, 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上进行了测试。

希望对某些人有所帮助。

干杯!


3

Swift:

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

    //if iPhone
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.Phone) {
        self.presentViewController(activityViewController, animated: true, completion: nil)
    } else { //if iPad
        // Change Rect to position Popover
        var popoverCntlr = UIPopoverController(contentViewController: activityViewController)
        popoverCntlr.presentPopoverFromRect(CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height/4, 0, 0), inView: self.view, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)

    }

2
在Swift 4中,以下代码适用于iPhone和iPad。根据文档,你需要使用适当的方式来呈现和取消呈现视图控制器,在iPad上,你必须使用弹出窗口来呈现视图控制器。 在其他设备上,你必须以模态方式呈现它。
 let activityViewController = UIActivityViewController(activityItems: activityitems, applicationActivities: nil)

    if UIDevice.current.userInterfaceIdiom == .pad {

        if activityViewController.responds(to: #selector(getter: UIViewController.popoverPresentationController)) {
            activityViewController.popoverPresentationController?.sourceView = self.view
        }
    }

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

1

swift = ios7/ ios8

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

//if iPhone
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.Phone) {
    // go on..
} else {
    //if iPad
    if activityViewController.respondsToSelector(Selector("popoverPresentationController")) {
        // on iOS8
        activityViewController.popoverPresentationController!.barButtonItem = self.shareButtonItem;
    }
}
self.presentViewController(activityViewController, animated: true, completion: nil)

1

我尝试了下面的代码并且它是有效的:

首先在你的视图控制器中放置一个条形按钮 然后创建一个IBOutlet:

@property(weak,nonatomic)IBOutlet UIBarButtonItem *barButtonItem;

接下来在.m文件中:yourUIActivityViewController.popoverPresentationController.barButtonItem = self.barButtonItem;


1
我正在使用Swift 5。 当我在iPad上点击我的应用程序中的“共享按钮”时,出现了崩溃问题。找到了一个解决方案。 步骤1:将“视图”对象(在对象库中搜索“UIView”)添加到Main.storyboard中。 步骤2:在ViewController.swift中创建@IBOutlet并分配任何名称(例如:view1) 步骤3:将上述名称(例如:view1)作为sourceView添加到我的“共享按钮”操作中。
@IBAction func Share(_ sender: Any) {
    let activityVC = UIActivityViewController(activityItems: ["www.google.com"], applicationActivities: nil)
    activityVC.popoverPresentationController?.sourceView = view1

    self.present(activityVC, animated: true, completion: nil)


}

我对Swift非常陌生,这个问题困扰了我一个星期。希望这能帮到其他人,所以分享一下解决方案。


0

我找到了这个解决方案

首先,你的呈现弹出视图控制器应该实现 <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;
}

-1
对于Swift 2.0版本,我发现如果你想将弹出窗口锚定到iPad上的分享按钮,以下方法是有效的。这假设你已经在工具栏中为分享按钮创建了一个outlet。
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)
        }

    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接