Метод setContentViewController в popover iOS8 вызывает сбой приложения

Метод setContentViewController в UIPopoverController, похоже, вызывает крушение приложения в iOS 8. Просто интересно, сталкивался ли кто-либо с этой проблемой в iOS 8. Это работает без каких-либо проблем в iOS 7.

Ошибка, указанная в исключении, кажется, вводит в заблуждение, поскольку она заявляет, что setContentViewController должен быть вызван после представления popover

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

Ответ 1

Я просто столкнулся с той же ошибкой, протестировавшей наше приложение под iOS 8. В нашем случае я принял сообщение об ошибке по номиналу и изменил шаблон, который у нас был в нескольких местах.

Образец, который нам пришлось изменить, был: (1) в нашем представлении контроллер init, создайте экземпляр экземпляра popover controller. (2) на каком-либо событии, установите свойство contentViewController контроллера popover для желаемого vc. (3) вызов presentPopoverFromRect на контроллере popover

и мы просто изменили шаг (2), чтобы повторно создать контроллер popover с нужным содержимым vc в качестве параметра init и прекратить настройку свойства contentViewController (как это всегда делается перед представлением popover).

Ответ 2

Я пережил эту же проблему и, наконец, решил ее.

У меня есть две кнопки, каждая из которых показывает свой собственный popover. Я повторно использовал тот же 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];

Ответ 3

Аналогично решению @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;
}

Проблема возникает при переназначении контроллера вида на существующий popover. Free и realloc popover перед назначением нового контроллера представления содержимого: это исправлено для меня.

Ответ 4

У меня была одна и та же проблема, и это было исправлено для меня.

Попробуйте это

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

Ответ 5

Добавьте эти два метода в основной класс UIwebview. добавьте <UIPopoverPresentationControllerDelegate> в свой класс webview interface.h. определить.

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

Ответ 6

У вас уже установлен контроллер содержимого:

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

Итак, почему бы просто не удалить строку?:

 [_popover setContentViewController:tableViewController];

Это должно работать.

Ответ 7

Если popover не отображается, когда вы вызываете [_popover setContentViewController:tableViewController];, приложение получит сбой.

Поскольку этот метод следует вызывать, когда popover отображается на экране.

Убедитесь, что ваш popover виден,

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

Ответ 8

   [self.popover dismissPopoverAnimated:YES]; //in case it 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];

Ответ 9

Вам не нужно создавать новый экземпляр UIPopoverController и не устанавливать новое свойство contentViewController после первого представления UIPopoverViewController. (это зависит от того, как вы уволяете вас popoverController)

Однако contentViewController не может быть изменен перед представлением popoverController.

Чтобы обходным способом проверить свойства popoverController.contentViewController. Если это nil, установите conntentViewController, иначе просто введите popover.

Если вы хотите изменить contentViewController сделать это после представления: используйте метод setContentViewController: анимированный:. Перед вызовом этого метода убедитесь, что popoverController.isPopoverVisible.