ios - 应用程序在 UISplitViewController 的 viewWillAppear 中崩溃

标签 ios objective-c ios8

我正在开发一个 iOS 应用程序,它使用选项卡栏在 UISplitViewController 子类的子类之间进行交换。直到 iOS 8 GM 种子(和发布版本),它工作正常。

但是,当使用 iOS 8 SDK 为运行 iOS 8 的 iPad 构建时,在切换到一个(且只有一个) View Controller 子类时,我不断遇到崩溃。这个崩溃会下降到父类(super class) (UISplitViewController) 的 viewWillAppear 方法,并且与在该方法中设置的 Popover 有关:

2014-09-29 09:24:13.526 AppName[51815:2369763] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIPopoverController initWithContentViewController:] must not be called with `nil`.'
*** First throw call stack:
(
    0   CoreFoundation                      0x0363adf6 __exceptionPreprocess + 182
    1   libobjc.A.dylib                     0x031fda97 objc_exception_throw + 44
    2   CoreFoundation                      0x0363ad1d +[NSException raise:format:] + 141
    3   UIKit                               0x012eaabe -[UIPopoverController _initWithContentViewController:popoverControllerStyle:] + 436
    4   UIKit                               0x0111eb43 -[UISplitViewController _setupHiddenPopoverControllerWithViewController:] + 122
    5   UIKit                               0x0111ed82 -[UISplitViewController _viewControllerHiding:] + 322
    6   UIKit                               0x0112556a -[UISplitViewController viewWillAppear:] + 189
    7   AppName                             0x001ac9c0 -[BaseSplitViewController viewWillAppear:] + 624
    8   AppName                             0x00342b82 -[HomeGlanceController viewWillAppear:] + 306
    9   UIKit                               0x00d7914f -[UIViewController _setViewAppearState:isAnimating:] + 545
    10  UIKit                               0x00d796ca -[UIViewController __viewWillAppear:] + 148
    11  UIKit                               0x00d910b1 -[UIViewController(UIContainerViewControllerProtectedMethods) beginAppearanceTransition:animated:] + 200
    12  UIKit                               0x00dc2dd3 -[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:] + 619
    13  UIKit                               0x00dc2352 -[UITabBarController transitionFromViewController:toViewController:] + 64
    14  UIKit                               0x00dbe545 -[UITabBarController _setSelectedViewController:] + 340
    15  UIKit                               0x00dbe3c7 -[UITabBarController setSelectedViewController:] + 193
    16  UIKit                               0x00dc222b -[UITabBarController _tabBarItemClicked:] + 326
    17  libobjc.A.dylib                     0x032137cd -[NSObject performSelector:withObject:withObject:] + 84
    18  UIKit                               0x00c1f79d -[UIApplication sendAction:to:from:forEvent:] + 99
    19  UIKit                               0x00c1f72f -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 64
    20  UIKit                               0x00f6228d -[UITabBar _sendAction:withEvent:] + 466
    21  libobjc.A.dylib                     0x032137cd -[NSObject performSelector:withObject:withObject:] + 84
    22  UIKit                               0x00c1f79d -[UIApplication sendAction:to:from:forEvent:] + 99
    23  UIKit                               0x00c1f72f -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 64
    24  UIKit                               0x00d52a16 -[UIControl sendAction:to:forEvent:] + 69
    25  UIKit                               0x00d52e33 -[UIControl _sendActionsForEvents:withEvent:] + 598
    26  UIKit                               0x00d52a4e -[UIControl sendActionsForControlEvents:] + 48
    27  UIKit                               0x00f670b1 -[UITabBar(Static) _buttonUp:] + 123
    28  libobjc.A.dylib                     0x032137cd -[NSObject performSelector:withObject:withObject:] + 84
    29  UIKit                               0x00c1f79d -[UIApplication sendAction:to:from:forEvent:] + 99
    30  UIKit                               0x00c1f72f -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 64
    31  UIKit                               0x00d52a16 -[UIControl sendAction:to:forEvent:] + 69
    32  UIKit                               0x00d52e33 -[UIControl _sendActionsForEvents:withEvent:] + 598
    33  UIKit                               0x00d5209d -[UIControl touchesEnded:withEvent:] + 660
    34  UIKit                               0x00c6faba -[UIWindow _sendTouchesForEvent:] + 874
    35  UIKit                               0x00c70595 -[UIWindow sendEvent:] + 791
    36  AppName                             0x004527b4 -[LHCWindow sendEvent:] + 100
    37  UIKit                               0x00c35aa9 -[UIApplication sendEvent:] + 242
    38  UIKit                               0x00c458de _UIApplicationHandleEventFromQueueEvent + 20690
    39  UIKit                               0x00c1a079 _UIApplicationHandleEventQueue + 2206
    40  CoreFoundation                      0x0355e7bf __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
    41  CoreFoundation                      0x035542cd __CFRunLoopDoSources0 + 253
    42  CoreFoundation                      0x03553828 __CFRunLoopRun + 952
    43  CoreFoundation                      0x035531ab CFRunLoopRunSpecific + 443
    44  CoreFoundation                      0x03552fdb CFRunLoopRunInMode + 123
    45  GraphicsServices                    0x0567524f GSEventRunModal + 192
    46  GraphicsServices                    0x0567508c GSEventRun + 104
    47  UIKit                               0x00c1de16 UIApplicationMain + 1526
    48  AppName                             0x0004c3de main + 222
    49  libdyld.dylib                       0x03b09ac9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

我发现有问题的 ViewController 在第一次显示时有三个 subview ,但是当我删除共享框架的两个中的任何一个时(通过删除 self.view addSubview 调用)崩溃仍然存在:

UIImageView, {{50, 10}, {260, 490}}
UIView, {{50, 10}, {260, 490}}
UIView, {{50, 510}, {670, 390}}

什么会导致 UISplitViewController 的子类中与弹出窗口相关的崩溃?


这是 BaseSplitViewController 中的 viewWillAppear:。运行异常断点在 [super viewWillAppear:animated] 行停止。

- (void)viewWillAppear:(BOOL)animated {
    iPadAppDelegate *appDelegate_iPad = [Utils getAppDelegateForDeviceType:DEVICE_TYPE_IPAD];
    if(![appDelegate_iPad getIsTabInitialised]) {
        return ;
    }
    DDLogVerbose(@"%@ appearing",[self class]);

    // Which tab is opening? Log it!
    NSString *screen = [kAnalyticsNavigationPrefix stringByAppendingString:NSStringFromClass([self class])];
    [AnalyticsManager logEvent:screen];

    // Ensure we don't cover anything with the status bar in iOS 7. It looks like
    // the orientation code wasn't being called anymore?
    [self adjustControllerForOrientation:[self interfaceOrientation]];

    [super viewWillAppear:animated];
}

BaseSplitViewController initviewDidLoad - awakeFromNib 未被覆盖。

- (id)init {
    if (self = [super init]) {
        [self setInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation];

    }
    return self;
}

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    DDLogVerbose(@"%@ loaded",[self class]);
    isModalViewPresent = NO;
    self.view.backgroundColor = [UIColor whiteColor];

    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        self.edgesForExtendedLayout = UIRectEdgeNone;
    }

}

HomeGlanceControllerBaseSplitViewController 的子类(它是 UISplitViewController 的子类)。它是 BSVC 的唯一一个崩溃的子类。

- (id)init {
    if (self = [super init]) {
        bIsAnyKeypadPresent = FALSE;
        //to create the favorite zone screen view
        favoriteScreenBackGroundView = [[UIView alloc] initWithFrame:CGRectMake(280, 0, 720, 430)];
        favoriteScreenbackGroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(40, 5, 667,405)];
        favoriteZoneScreenMainView                  = [[UIView alloc] initWithFrame:CGRectMake(20, 40 ,640,340)];

        favoriteKeypadScreenMainView = [[UIView alloc] initWithFrame:CGRectMake(10, 50 ,200,330)];

        // Initialize the layout for the Favorite Controller.
        [self initFavoriteLayoutCoordinates];
        UITabBarItem * tabBarItem = [[UITabBarItem alloc]initWithTitle:HomeGlanceTabTitle
                                                                 image:[Utils getImageNamed:HomeGlanceIcon] 
                                                                   tag:1];
        tabBarItem.selectedImage = [Utils getImageNamed:HomeGlanceSelectedIcon];

        self.tabBarItem = tabBarItem;
        tabBarItem = nil;

        // pick the co-ordinates of the favorite view from the layout array.
        if ([favControlCoordinatesArray count]>layoutID) {
            [self setControllerCoordinates:[favControlCoordinatesArray objectAtIndex:layoutID]];
        }
    }

    return self;
}

- (void) viewDidLoad {
    // I've tried commenting all but the super call out. The crash remains
    [self createImageViewForFavorites];

    // to create the View for favorite zone
    [self createBackGroundViewForFavoriteZoneScreen];
    [self createFavoriteZoneScreenToolbar];
    [self createFavoriteZoneScreenMainView];
    [self createFavoriteKeypadScreenToolbar]; 

    [super viewDidLoad];
}

- (void)viewWillAppear : (BOOL) animated {
    [super viewWillAppear:animated];

    [self startTimer];
    iPadAppDelegate *appDelegate_iPad = [Utils getAppDelegateForDeviceType:DEVICE_TYPE_IPAD];
    if(![appDelegate_iPad getIsTabInitialised])
    {
        return;
    }
    [self createFavoriteZoneScreenMainView];

    [self createFavoriteKeypadScreenMainView];

    // Snipped methods that don't impact the UI directly (commented out in this build)
}

显然崩溃只发生在 iPad 处于(或转向)纵向模式时:

  • 可以选择选项卡而不会在横向模式下崩溃,但在该选项卡上旋转到纵向模式会在 super willRotateToInterfaceOrientation:duration: 时崩溃。
  • 如果选项卡在纵向模式下被选中,应用程序将在 super viewWillAppear:
  • 上崩溃

最终原因似乎是相同的([UIPopoverController initWithContentViewController:] 不能用 nil 调用。)。

最佳答案

出现默认的preferredDisplayModeUISplitViewControllerDisplayModeAutomatic,并且 UISplitViewController 正在做一些事情,涉及在它具有该显示模式并调用 viewWillAppear 或旋转时以纵向方式创建弹出 Controller 。

为避免崩溃,我在 viewDidLoad 方法中添加了更改显示模式的代码:

[self setPreferredDisplayMode:UISplitViewControllerDisplayModeAllVisible];

关于ios - 应用程序在 UISplitViewController 的 viewWillAppear 中崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26104081/

相关文章:

ios - 如何暂停 dispatch_queue_t 及其创建的队列

objective-c - UIViewController 知道它是被推送还是弹出?

ios - 我如何找出 Objective-C 泛型类型?

ios - NSMutableString 保留/复制是相同的(复制不起作用?)

ios - 使用 phimagemanager 将图像保存到自定义相册?

iOS 应用程序 Modbus 使用 Swift 读/写

iOS:禁止 "Open in..."菜单并立即在特定应用程序中打开附加的电子邮件文件

ios - 如何更改 UINavigationItem 字体?

从底部快速启动 tableView(反向 tableView)

objective-c - iOS 8 删除今日扩展