顯示具有 presentViewController 標籤的文章。 顯示所有文章
顯示具有 presentViewController 標籤的文章。 顯示所有文章

2014年10月1日 星期三

iOS 開發筆記 - -[######## _viewControllerForSupportedInterfaceOrientationsWithDismissCheck:]: unrecognized selector sent to instance 0x########'

這幾晚和此 crash log 對抗了一下 Orz 這是一個在 iOS 8 才出現,但在 iOS 7 可以活得好好的 bug ,簡介一下狀況:

  • Project 採用 SingleView 建立,簡稱 ViewController1
  • 在 ViewController1 中,動態建立 UINavigationController ,並 push ViewController2 後,再透過 presentViewController 呈現,也就是在 ViewController1 沒有 UINavigationController 但 ViewController2 有。
  • 在 ViewController2 中,此 shouldAutorotate 皆回傳 YES

接著,只要在 ViewController2 中,透過 dismiss 返回到 ViewController1 時,再進行 device rotation 後,這時就會看到 crash log。但一樣的 code 擺在 iOS 7 卻能夠正常運作,並且可透過時間差進行 device rotation 觀看出發動 _viewControllerForSupportedInterfaceOrientationsWithDismissCheck 的物件,並非固定:

  • -[__NSCFString _viewControllerForSupportedInterfaceOrientationsWithDismissCheck:]: unrecognized selector sent to instance 0x########
  • -[UIStatusBarStyleRequest _viewControllerForSupportedInterfaceOrientationsWithDismissCheck:]: unrecognized selector sent to instance 0x########
  • -[__NSBlockVariable__ _viewControllerForSupportedInterfaceOrientationsWithDismissCheck:]: unrecognized selector sent to instance 0x########
  • ...

解法?就是從 ViewController1 就開始用 UINavigationController 吧!接著都走 UINavigationController 控制方式,例如 push、pop 後,即可避開這奇妙的問題。

2014年8月4日 星期一

iOS 開發筆記 - Warning: Attempt to present YourViewController on ViewController whose view is not in the window hierarchy!

有點久沒有純手工寫 UI 互動類的 Orz 測試時不知為何在 viewDidLoad 彈跳新的 YourViewController 時,會出現這個 Warning 並且沒有任何結果。

查詢了一下,發現要在 viewDidAppear 呼叫就能避免現象,有人說是在 viewDidLoad 時沒有 Window Hierarchy 資訊。擺在 viewDidAppear 時,若彈跳的 YourViewController 關閉時,切入 ViewController 時,又進入 viewDidAppear 又會彈跳 YourViewController 出來。

總之,測試時應該可以先這樣用吧,若要正式使用大概要多加一些條件判斷:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [self presentViewController:[[YourViewController alloc] init] animated:YES completion:NULL];
}
參考資料
@ Updated 2014-08-17: 另一招則是在 viewDidLoad 中,採用 dispatch_async -> dispatch_get_main_queue 使用也行。

- (void)viewDidLoad
{
    [super viewDidLoad];

    dispatch_async(dispatch_get_main_queue(), ^{
        YourViewController *v = [[YourViewController alloc] init];
        [self presentViewController:v animated:YES completion:^{}];
    });
}