1

我有一個應用程序,我正在努力,這是普遍的。在iphone版本中,我使用一個標準的UINavigationController堆棧進行導航,並且與世界一切都很好。但是,在ipad版本中,我使用的是UISplitViewContoller nav,但是登錄界面只是標準的UIViewControllers。直到最近,當我不得不在細節方面改變導航的時候,這一切都很好。現在基本上取決於主裝載的內容,我必須在詳細導航控制器中清除堆棧並替換它的根目錄。從那時起,有時當你打註銷,每次會話超時,並且用戶發送到登錄界面的應用程序崩潰與:的ios appDelegate窗口setRootViewController崩潰

* thread #1: tid = 0x140896, 0x0000000102143fcb libobjc.A.dylib`objc_msgSend + 11, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT) 
frame #0: 0x0000000102143fcb libobjc.A.dylib`objc_msgSend + 11 
frame #1: 0x000000010109ffb2 UIKit`-[UISplitViewController _calculateDelegateHiddenMasterOrientations] + 48 
frame #2: 0x00000001010a284b UIKit`-[UISplitViewController hidesMasterViewInLandscape] + 42 
frame #3: 0x000000010109fec7 UIKit`-[UISplitViewController _isMasterViewShownByDefault] + 75 
frame #4: 0x000000010109fee7 UIKit`-[UISplitViewController _isMasterViewShown] + 23 
frame #5: 0x00000001010a2e18 UIKit`-[UISplitViewController viewWillDisappear:] + 70 
frame #6: 0x0000000100dd6e42 UIKit`-[UIViewController _setViewAppearState:isAnimating:] + 563 
frame #7: 0x0000000100dd7ef8 UIKit`-[UIViewController viewWillMoveToWindow:] + 316 
frame #8: 0x0000000100d30e00 UIKit`-[UIView(Hierarchy) _willMoveToWindow:] + 430 
frame #9: 0x0000000100d2fd2a UIKit`__UIViewWillBeRemovedFromSuperview + 346 
frame #10: 0x0000000100d2fb07 UIKit`-[UIView(Hierarchy) removeFromSuperview] + 67 
frame #11: 0x0000000100d13f95 UIKit`-[UIWindow setRootViewController:] + 262 
* frame #12: 0x0000000100047471 Callidus Enablement`__35+[CEInterfaceFunctions OpenLoginVC]_block_invoke(.block_descriptor=<unavailable>) + 609 at CEInterfaceFunctions.m:186 
frame #13: 0x000000010336f851 libdispatch.dylib`_dispatch_call_block_and_release + 12 
frame #14: 0x000000010338272d libdispatch.dylib`_dispatch_client_callout + 8 
frame #15: 0x00000001033723fc libdispatch.dylib`_dispatch_main_queue_callback_4CF + 354 
frame #16: 0x00000001024b6289 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9 
frame #17: 0x0000000102403854 CoreFoundation`__CFRunLoopRun + 1764 
frame #18: 0x0000000102402d83 CoreFoundation`CFRunLoopRunSpecific + 467 
frame #19: 0x00000001030fcf04 GraphicsServices`GSEventRunModal + 161 
frame #20: 0x0000000100cdde33 UIKit`UIApplicationMain + 1010 
frame #21: 0x000000010005f523 Callidus Enablement`main(argc=1, argv=0x00007fff5fbfec50) + 115 at main.m:16 

例子我是如何轉換的細節堆棧:

if (![appDelegate.window.rootViewController isKindOfClass:[UISplitViewController class]]) { 
    appDelegate.window.rootViewController = [[UIStoryboard storyboardWithName:@"Main_iPad" bundle:nil] instantiateViewControllerWithIdentifier:@"split"]; 
} 
UISplitViewController *splitViewController = (UISplitViewController *)appDelegate.window.rootViewController; 
NSArray* VCs = splitViewController.viewControllers; 
UINavigationController* masterNav = (UINavigationController*)VCs[0]; 
UINavigationController* detailNav = (UINavigationController*)VCs[1]; 

[masterNav popToRootViewControllerAnimated:NO]; 

[detailNav setViewControllers:@[[masterNav.storyboard instantiateViewControllerWithIdentifier:@"recent"]] animated:NO]; 
登錄屏幕加載代碼的

例子:

dispatch_async(dispatch_get_main_queue(), ^{ 
    AppDelegate* appDelegate = [[UIApplication sharedApplication] delegate]; 
    UIStoryboard* sb; 
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 
     sb = [UIStoryboard storyboardWithName:@"Main_iPad" bundle:nil]; 
    } else { 
     sb = [UIStoryboard storyboardWithName:@"Main_iPhone" bundle:nil] ; 
    } 
    NSLog(@"sb:%@ appd:%@ win:%@ root:%@",sb,appDelegate,appDelegate.window,appDelegate.window.rootViewController); 

    UIViewController* vc =[sb instantiateViewControllerWithIdentifier:@"login"]; 
    NSLog(@"vc:%@",vc); 
    appDelegate.window.rootViewController = vc;//Crash happens HERE 
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) { 
     [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; 
    } 
    [appDelegate.window makeKeyAndVisible]; 
}); 

任何幫助將是巨大的!

+2

您是否嘗試在調用'appDelegate.window.rootViewController = vc;'之前將委託設置爲nil'splitViewController.delegate = nil'? –

+0

@Visput你救了我一天的人!只是設置零停止崩潰。 –

回答

2

它可能與動畫或轉換尚未在分割控制器上完成有關。也許一個警報視圖?

無論如何,我會建議您在未更改的rootController上模態地「登錄」登錄控制器,因此您不必調整控制器並可以在登錄控制器中輸入/輸出動畫。


例如:presentViewController:animated:completion:

+0

似乎我沒有想過每個案例我都需要延遲......我在所有註銷電話周圍放了半秒的延遲,現在它似乎完美地工作^^;謝謝!出於好奇,因爲root是UISplitVC,你會如何推薦登錄控制器? –

+0

nvm,發言並點擊太快>。 –

+0

呈現「模態」。 – Rivera

0

有你的代碼的各種問題。首先,你應該設置應用程序的委託

application:didFinishLaunchingWithOptions: 

你應該避免玩它的應用程序推出的這一特殊時刻以外的方法中的窗口rootController。其次,考慮到你的第一段代碼,你究竟在改變rootController?是不是你的線:

if (![appDelegate.window.rootViewController isKindOfClass:[UISplitViewController class]]) { 

說你已經有一個?爲什麼這個測試?

然後,這條線是沒用的:

[masterNav popToRootViewControllerAnimated:NO]; 

假設你沒有做一些在masterNav類的實例的方法initWithCoder:特(如果我們相信投放在實例面前,它是一個標準UINavigationController,但這可能只是隱藏故事板內的真相)。

現在,要真正回答您的問題,您需要指出「登錄屏幕加載代碼」的確切位置。在什麼課上,叫什麼?爲什麼你在dispatch_async(dispatch_get_main_queue(), ^{...區塊內調用這個?

通常情況下,您應該在application:didFinishLaunchingWithOptions:方法中,不管怎樣,它都在主線程(==主隊列)上調用。

最後一個問題:你爲什麼要在兩個不同的地方設置窗口根控制器?你的代碼對於你試圖解決的問題是非常複雜的(否則這是完全相關的)。

+0

在應用程序中:didFinishLaunchingWithOptions:我將rootViewController設置爲登錄控制器(UIViewController),或者在會話仍然良好的情況下分割控制器。現在,如果他們的會話超時或他們想註銷,我回到主線程切換出rootViewController的基礎上,他們要走的方式...我一直在做ios代碼一段時間,有沒有更好的方法來像這樣轉換? –

+0

還是你建議使用presentModalViewController:animated:? –

+0

對不起(我剛剛醒來):presentViewController:animated:completion:就是我的意思。 –