popover iOS8中的setContentViewController方法导致应用程序崩溃

时间:2014-09-11 11:50:30

标签: ios ios8 uipopovercontroller xcode6 uipopover

UIPopoverController中的setContentViewController方法似乎导致iOS 8中的应用程序崩溃。只是想知道是否还有其他人在iOS 8中遇到此问题。这在iOS 7中没有任何问题。

异常中指出的错误似乎有误导性,因为它声明应该在呈现popover之后调用setContentViewController

- (void)buttonPressed {

UIViewController *tableViewController = [UIViewController new];

if(_popover == nil){

    _popover = [[UIPopoverController alloc] initWithContentViewController:tableViewController];

    [_popover presentPopoverFromRect:CGRectMake(self.textField.frame.size.width / 2, self.textField.frame.size.height / 1, 1, 1) inView:self.textField permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}else{
    [_popover setContentViewController:tableViewController];
}    

}

这是崩溃中的堆栈跟踪,

2014-09-11 16:48:39.904 iOS 8 Rotation[3969:67869] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIPopoverController setContentViewController:animated:] can only be called after the popover has been presented.'
*** First throw call stack:
(
    0   CoreFoundation                      0x01c79df6 __exceptionPreprocess + 182
    1   libobjc.A.dylib                     0x01903a97 objc_exception_throw + 44
    2   CoreFoundation                      0x01c79d1d +[NSException raise:format:] + 141
    3   UIKit                               0x00b1946f -[UIPopoverPresentationController _setContentViewController:animated:] + 89
    4   UIKit                               0x009bb1b4 -[UIPopoverController setContentViewController:animated:] + 155
    5   UIKit                               0x009bb114 -[UIPopoverController setContentViewController:] + 48
    6   iOS 8 Rotation                      0x00046ca5 -[MianViewController buttonPressed] + 933
    7   libobjc.A.dylib                     0x019197cd -[NSObject performSelector:withObject:withObject:] + 84
    8   UIKit                               0x002ef79d -[UIApplication sendAction:to:from:forEvent:] + 99
    9   UIKit                               0x002ef72f -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 64
    10  UIKit                               0x00422a16 -[UIControl sendAction:to:forEvent:] + 69
    11  UIKit                               0x00422e33 -[UIControl _sendActionsForEvents:withEvent:] + 598
    12  UIKit                               0x0042209d -[UIControl touchesEnded:withEvent:] + 660
    13  UIKit                               0x0033faba -[UIWindow _sendTouchesForEvent:] + 874
    14  UIKit                               0x00340595 -[UIWindow sendEvent:] + 791
    15  UIKit                               0x00305aa9 -[UIApplication sendEvent:] + 242
    16  UIKit                               0x003158de _UIApplicationHandleEventFromQueueEvent + 20690
    17  UIKit                               0x002ea079 _UIApplicationHandleEventQueue + 2206
    18  CoreFoundation                      0x01b9d7bf __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
    19  CoreFoundation                      0x01b932cd __CFRunLoopDoSources0 + 253
    20  CoreFoundation                      0x01b92828 __CFRunLoopRun + 952
    21  CoreFoundation                      0x01b921ab CFRunLoopRunSpecific + 443
    22  CoreFoundation                      0x01b91fdb CFRunLoopRunInMode + 123
    23  GraphicsServices                    0x040cc24f GSEventRunModal + 192
    24  GraphicsServices                    0x040cc08c GSEventRun + 104
    25  UIKit                               0x002ede16 UIApplicationMain + 1526
    26  iOS 8 Rotation                      0x0004774d main + 141
    27  libdyld.dylib                       0x0224cac9 start + 1
    28  ???                                 0x00000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

9 个答案:

答案 0 :(得分:4)

我刚刚在iOS 8下测试了我们的应用程序时遇到同样的错误。在我们的例子中,我在面值处获取了错误消息并更改了我们在几个地方的模式。

我们必须改变的模式是: (1)在我们的视图控制器的init中,实例化一个弹出控制器实例。 (2)在某些事件中,将popover控制器的contentViewController属性设置为所需的vc。 (3)在弹出控制器上调用presentPopoverFromRect

我们只需更改步骤(2)以使用所需内容vc作为init参数重新实例化弹出控制器,并停止设置contentViewController属性(因为我们在呈现弹出窗口之前始终执行此操作)。

答案 1 :(得分:3)

我遇到了同样的问题并最终解决了它。

我有两个按钮,每个按钮都显示自己的弹出窗口。我重复使用相同的UIPopoverController来显示它们。第一次点击工作正常,但如果你点击另一个点击应用程序崩溃。

我解决它的方法是在每次点击时创建一个新的UIPopoverController:

importImagePickerControlPopoverController=[[UIPopoverController alloc] initWithContentViewController:pickerController];
[importImagePickerControlPopoverController setDelegate:self];

switch(pickerType)
{
    case UIImagePickerControllerSourceTypePhotoLibrary:
    case UIImagePickerControllerSourceTypeSavedPhotosAlbum:
        [importImagePickerControlPopoverController setPopoverContentSize:CGSizeMake(320, 300) animated:YES];
        break;
    case UIImagePickerControllerSourceTypeCamera:
        [importImagePickerControlPopoverController setPopoverContentSize:CGSizeMake(640, 640) animated:YES];
        break;
}
[importImagePickerControlPopoverController setContentViewController:pickerController];

答案 2 :(得分:2)

与@ user3495742解决方案类似:

-(void)testAndSetPopoverWithVc:(UIViewController*)vc {
    if (popover4Menu) {
        if ([popover4Menu isPopoverVisible]) {
            [popover4Menu setContentViewController:vc animated:YES];
            return;
        } else {
            popover4Menu=nil;
        }
    };
    popover4Menu=[[UIPopoverController alloc] initWithContentViewController:vc];
    popover4Menu.delegate=self;
}

将视图控制器重新分配给现有的弹出窗口时问题会出现。 在分配新的内容视图控制器之前,自由和重新分配弹出窗口:这对我来说是固定的。

答案 3 :(得分:0)

我遇到了同样的问题,这就是为我解决的问题。

试试这个

- (void)buttonPressed{

  UIViewController *tableViewController = [UIViewController new];

  //Check if the popover is nil or not visible
  if(_popover == nil || _popover.popoverVisible == false){

    _popover = [[UIPopoverController alloc] initWithContentViewController:tableViewController];

    [_popover presentPopoverFromRect:CGRectMake(self.textField.frame.size.width / 2, self.textField.frame.size.height / 1, 1, 1) inView:self.textField permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
  }else{
    [_popover setContentViewController:tableViewController];
  }
}

答案 4 :(得分:0)

将这两个方法添加到UIwebview主类中。 在webview interface.h类中添加<UIPopoverPresentationControllerDelegate>。 定义。

@property (strong, nonatomic) UIPopoverPresentationController *pop;

然后

@synthesize pop;

- (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;
        pop = destNav.viewControllers.firstObject;

        // This is the important part
        UIPopoverPresentationController *popPC = destNav.popoverPresentationController;
        popPC.delegate = self;
    }
}
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
    return UIModalPresentationNone;
}

答案 5 :(得分:0)

您已经设置了内容视图控制器:

_popover = [[UIPopoverController alloc] initWithContentViewController:tableViewController]; 
                                                                        ↑
                                                                      Here

那么,为什么不删除该行?:

 [_popover setContentViewController:tableViewController];

这应该有效。

答案 6 :(得分:0)

如果在调用[_popover setContentViewController:tableViewController];时看不到popover,则app会崩溃。

因为当屏幕上显示popover时应该调用此方法。

确保您的弹出窗口可见

if(_popover != nil && [_popover isPopoverVisible] == YES)
{
   [_popover setContentViewController:tableViewController];
}else
{
       //create new popover object if _popover is nil or present it
}

答案 7 :(得分:0)

   [self.popover dismissPopoverAnimated:YES]; //in case it's already showing.  
   self.popover = nil; // N.B. this is not the same as popover = nil. 
   self.popover = [[UIPopoverController alloc] initWithContentViewController:tableViewController];
   [self.popover  presentPopoverFromRect:CGRectMake(self.textField.frame.size.width /
   2, self.textField.frame.size.height / 1, 1, 1) inView:self.textField
   permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];

答案 8 :(得分:0)

首次出现 UIPopoverViewController后,您不需要创建 UIPopoverController 的新实例,也不需要设置新的 contentViewController 属性。(取决于具体方法)你解雇了你popoverController)

但是,在popoverController演示之前无法更改 contentViewController

要解决此问题,请检查 popoverController.contentViewController 属性。如果 nil ,请设置 conntentViewController ,否则只显示popover。

如果要更改 contentViewController ,请在演示后执行:使用 setContentViewController:animated:方法。 在调用此方法之前,请检查 popoverController.isPopoverVisible