简体   繁体   English

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

[英]setContentViewController method in popover iOS8 causes app crash

The setContentViewController method in UIPopoverController seems to be causing an app crash in iOS 8. Just wondering if anybody else also faced this issue in iOS 8. This works without any issue in iOS 7. UIPopoverController中的setContentViewController方法似乎导致iOS 8中的应用程序崩溃。只是想知道是否还有其他人在iOS 8中遇到此问题。这在iOS 7中没有任何问题。

The error pointed in the exception seems to be misleading as it states that the setContentViewController should be called after presenting the 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];
}    

} }

Here is Stack trace from the crash, 这是崩溃的堆栈跟踪,

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

I just encountered this same error testing our app under iOS 8. In our case, I took the error message at face value and changed a pattern we had in a few places. 我刚刚在iOS 8下测试了我们的应用程序时遇到了同样的错误。在我们的例子中,我在面值处获取了错误消息并更改了我们在几个地方的模式。

The pattern we had to change was: (1) in our view controller's init, instantiate a popover controller instance. 我们必须改变的模式是:(1)在我们的视图控制器的init中,实例化一个弹出控制器实例。 (2) on some event, set the popover controller's contentViewController property to the desired vc. (2)在某些事件中,将popover控制器的contentViewController属性设置为所需的vc。 (3) call presentPopoverFromRect on the popover controller (3)在弹出控制器上调用presentPopoverFromRect

and we simply changed step (2) to re-instantiate the popover controller with the desired content vc as an init parameter and ceased setting the contentViewController property (as we're always doing it prior to presenting the popover). 我们只需更改步骤(2)以使用所需内容vc作为init参数重新实例化popover控制器并停止设置contentViewController属性(因为我们在呈现popover之前总是这样做)。

I was experiencing this same issue and finally solved it. 我遇到了同样的问题并最终解决了它。

I have two buttons, each one shows its own popover. 我有两个按钮,每个按钮显示自己的弹出窗口。 I was reusing the same UIPopoverController to show both of them. 我重复使用相同的UIPopoverController来显示它们。 The first click worked fine, but then if you clicked the other one the app crashed. 第一次点击工作正常,但如果你点击另一个点击应用程序崩溃。

The way I solved it is create a new UIPopoverController on each click: 我解决它的方法是在每次点击时创建一个新的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];

Similar to @user3495742 solution: 与@ 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;
}

Problem rises when reassigning a view controller to an existing popover. 将视图控制器重新分配给现有的弹出窗口时问题会出现。 Free and realloc popover before assigning new content view controller: this fixed for me. 在分配新的内容视图控制器之前自由和realloc popover:这对我来说是固定的。

I had the same issue and this is what fixed it for me. 我遇到了同样的问题,这就是为我解决的问题。

Try This 试试这个

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

Add these two methods into your UIwebview main class. 将这两个方法添加到UIwebview主类中。 add <UIPopoverPresentationControllerDelegate> in your webview interface.h class as well. 在webview interface.h类中添加<UIPopoverPresentationControllerDelegate> define . 定义。

@property (strong, nonatomic) UIPopoverPresentationController *pop;

then 然后

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

You have already have the content view controller set: 您已经设置了内容视图控制器:

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

So, why not just delete the line?: 那么,为什么不删除该行?:

 [_popover setContentViewController:tableViewController];

That should work. 这应该工作。

If popover is not visible when you are calling [_popover setContentViewController:tableViewController]; 如果在调用[_popover setContentViewController:tableViewController];时看[_popover setContentViewController:tableViewController]; , app will get crash. ,应用程序将崩溃。

Because this method should be called when popover is visible on the screen. 因为当屏幕上显示popover时应该调用此方法。

Make sure your popover is visible, 确保您的弹出窗口可见,

if(_popover != nil && [_popover isPopoverVisible] == YES)
{
   [_popover setContentViewController:tableViewController];
}else
{
       //create new popover object if _popover is nil or present it
}
   [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];

You do not need to create new instance of UIPopoverController neither set new contentViewController property after you first present UIPopoverViewController. 首次出现UIPopoverViewController后,您不需要创建新的UIPopoverController实例也不需要设置新的contentViewController属性 (it depends on how you dismiss you popoverController) (这取决于你如何解雇你popoverController)

However contentViewController can't be changed before popoverController presentation. 但是,在popoverController演示之前无法更改contentViewController

To workaround check popoverController.contentViewController properties. 要解决此问题,请检查popoverController.contentViewController属性。 If it is nil , set conntentViewController , otherwise just present popover. 如果是nil ,请设置conntentViewController ,否则只显示popover

If you want to change contentViewController do it after presentation: use setContentViewController:animated: method. 如果你想更改contentViewController,请在演示之后执行:使用setContentViewController:animated:方法。 Check that popoverController.isPopoverVisible before call this method. 在调用此方法之前检查popoverController.isPopoverVisible

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM