2016-06-01 13 views
7

私はUISplitViewControllerを追加する既存のiPhoneアプリを持っています。 iPadの部品は魅力的に機能しますが、iPhone 6(S)Plusで確実にクラッシュしています。iPhone 6 Plus UISplitViewControllerが再帰的な_canBecomeDeepestUnmbiguousResponderでクラッシュする

セットアップ - マスターはUITabBarControllerです。初期詳細は、プレースホルダロゴ表示付きのビューです。オブジェクトが選択されると、詳細はUITabBarControllerに置き換えられます。

アイテムを選択してiPhone 6 Plusの詳細を開き、縦(詳細のみ表示)から横(マスターが表示される)に回転すると、クラッシュします。これは、プレースホルダ詳細ビューでの回転では発生しません。

クラッシュする前に、デリゲートメソッドprimaryViewControllerForExpandingSplitViewControllersplitViewController(splitViewController: UISplitViewController, separateSecondaryViewControllerFromPrimaryViewControllerを呼び出します。しかし、すべてがiPad上で正常に動作します。

私は既にたくさんの検索をしており、このタイプのクラッシュのカップルtwitterの言及を見ただけです。設定したり、設定しないようなものは、displayModeButtonItemは役に立ちません。

私は新鮮なプロジェクトでこのクラッシュを再作成 - それはここからダウンロードすることができます: https://github.com/sschale/SplitViewCrash/

クラッシュログ:

Crashed Thread:  0 Dispatch queue: com.apple.main-thread 

Exception Type:  EXC_BAD_ACCESS (SIGSEGV) 
Exception Codes:  KERN_PROTECTION_FAILURE at 0x00007fff53609ff8 
Exception Note:  EXC_CORPSE_NOTIFY 

VM Regions Near 0x7fff53609ff8: 
    MALLOC_TINY   00007f8405000000-00007f8405300000 [ 3072K] rw-/rwx SM=PRV 
--> STACK GUARD   00007fff4fe0a000-00007fff5360a000 [ 56.0M] ---/rwx SM=NUL stack guard for thread 0 
    Stack     00007fff5360a000-00007fff53dff000 [ 8148K] rw-/rwx SM=COW thread 0 

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 liboainject.dylib    0x000000010e5e59b2 
0 liboainject.dylib    0x000000010e5e59b2 

_writeEventToSharedMemory + 27 
1 liboainject.dylib    0x000000010e5e55d7 _OARecordFinalEvent + 1161 
2 liboainject.dylib    0x000000010e5e79f1 ___swapMethods_block_invoke_6 + 338 
3 libobjc.A.dylib     0x000000010f4f9b6b weak_read_no_lock + 89 
4 libobjc.A.dylib     0x000000010f4fa4c6 objc_loadWeakRetained + 104 
5 com.apple.UIKit     0x00000001110510b6 -[UIViewController presentedViewController] + 58 
6 com.apple.UIKit     0x0000000111033fc6 -[UIViewController _canBecomeDeepestUnambiguousResponder] + 31 
7 com.apple.UIKit     0x0000000111033fde -[UIViewController _canBecomeDeepestUnambiguousResponder] + 55 
8 com.apple.UIKit     0x0000000111033fde -[UIViewController _canBecomeDeepestUnambiguousResponder] + 55 
9 com.apple.UIKit     0x0000000111033fde -[UIViewController _canBecomeDeepestUnambiguousResponder] + 55 
10 com.apple.UIKit     0x0000000111033fde -[UIViewController _canBecomeDeepestUnambiguousResponder] + 55 
//(500 more of those) 
.... 

Thread 1:: Dispatch queue: com.apple.libdispatch-manager 
0 libsystem_kernel.dylib   0x0000000116e49ee2 kevent64 + 10 
1 libdispatch.dylib    0x0000000116ac57f0 _dispatch_mgr_invoke + 260 
2 libdispatch.dylib    0x0000000116ac558a _dispatch_mgr_thread + 54 

Thread 2: 
0 libsystem_kernel.dylib   0x0000000116e495e2 __workq_kernreturn + 10 
1 libsystem_pthread.dylib   0x0000000116e0d578 _pthread_wqthread + 1283 
2 libsystem_pthread.dylib   0x0000000116e0b341 start_wqthread + 13 

Thread 3: 
0 libsystem_kernel.dylib   0x0000000116e495e2 __workq_kernreturn + 10 
1 libsystem_pthread.dylib   0x0000000116e0d578 _pthread_wqthread + 1283 
2 libsystem_pthread.dylib   0x0000000116e0b341 start_wqthread + 13 

Thread 4: 
0 libsystem_kernel.dylib   0x0000000116e495e2 __workq_kernreturn + 10 
1 libsystem_pthread.dylib   0x0000000116e0d578 _pthread_wqthread + 1283 
2 libsystem_pthread.dylib   0x0000000116e0b341 start_wqthread + 13 

Thread 5: 
0 libsystem_kernel.dylib   0x0000000116e495e2 __workq_kernreturn + 10 
1 libsystem_pthread.dylib   0x0000000116e0d578 _pthread_wqthread + 1283 
2 libsystem_pthread.dylib   0x0000000116e0b341 start_wqthread + 13 

答えて

4

これはあまりにもiPadでクラッシュします。マルチタスキングを使用して、アプリのサイズをコンパクトなサイズ(たとえば1/3の画面)に変更し、「詳細を起動」ボタンを押してから、「通常の幅」にサイズを変更します。

コンパクトな幅の場合、分割ビューコントローラは「折りたたまれています」。つまり、それはもはや、別々のプライマリビューコントローラとセカンダリビューコントローラを同時に表示するのではなく、単一のビューコントローラ階層にそれらを「折りたたむ」ということです。その環境にいるときは、賢明に行動するためにしばしばあなたの助けが必要です。プライマリビューコントローラとセカンダリビューコントローラの両方がUINavigationControllerの場合は、デフォルトの動作がうまく動作しますが、それ以外の場合はうまく動作しません。

(アプリケーションでは、プライマリはUITabBarControllerです。また、 "Launch Detail"を1回だけ実行すると、セカンダリもUITabBarControllerになりますので、その設計を再考することができます。

アプリの「詳細を起動」ボタンが有効にUISplitViewControllerに、このメソッドを呼び出して、「詳細の表示」セグエを、実行します。

public func showDetailViewController(vc: UIViewController, sender: AnyObject?) 

注ヘッダー内のコメント:

// In a horizontally-compact environment the master view controller 
// or detail view controller is sent the showViewController:sender: 
// message. If neither one of them provide an implementation for this 
// method then it will fall back to a full screen presentation. 

「マスタビューコントローラまたは詳細ビューコントローラ」とは、現在表示されているビューコントローラを意味します。この場合、UITabBarControllerが表示されます。しかし、UITabBarControllerは、十分な情報がないため、showViewController()のために何も実装していません。どこにビューコントローラが表示されますか?それは新しいタブを追加するか、古いタブを置き換えるか、それとも何ですか?

その結果、フォールバックのフルスクリーンプレゼンテーションが表示されます。私はあなたが実際にそのユーザーエクス

その後、サイズが通常に戻って分割ビューコントローラが拡大されると、プレゼンテーションが混乱し、結局クラッシュします。 (デフォルトではあまり良くないとはどういう意味ですか?)

これを解決する1つの方法は、showDetailを処理するためのデリゲートメソッドを実装することです。幅がコンパクトの場合は、新しいView Controllerを配置するView Controllerを明示的に探して、それを行います。私はあなたがおそらく最初のタブにナビゲーションコントローラにプッシュしたいと思う:

func splitViewController(splitViewController: UISplitViewController, showDetailViewController vc: UIViewController, sender: AnyObject?) -> Bool 
{ 
    if splitViewController.traitCollection.horizontalSizeClass == .Compact { 
     // The default implementation will not handle this properly. 
     // Find the appropriate navigation controller and push onto it. 
     // It would be better to have a direct outlet to the appropriate navigation controller, 
     // but this will work for an example... 

     if let tabBarController = splitViewController.viewControllers.first as? UITabBarController { 
      if let navController = tabBarController.viewControllers?.first as? UINavigationController { 
       navController.pushViewController(vc, animated: true) 

       // we handled the "show detail", so split view controller, 
       // please don't do anything else 
       return true 
      } 
     } 
    } 

    // we did not handle the "show detail", so split view controller, 
    // please do your default behavior 
    return false 
} 

あなたがそれを行う場合は、あなたも、このデリゲートメソッドを実装することになるでしょう。あなたの詳細な返信用

optional public func splitViewController(
    splitViewController: UISplitViewController 
    separateSecondaryViewControllerFromPrimaryViewController 
     primaryViewController: UIViewController) -> UIViewController? 
+0

ありがとう:サイズはバック正規に変更された場合、あなたはそれを返し、同じナビゲーションコントローラのオフそのビューコントローラをポップし、「拡大」を扱うことになるでしょう。私のUIは、もともとは 'UITabBarController'からレコードが選択された後の' UITabBarController'へのモーダルなセグメントでした(ただし、レコード以外の項目に必要な他のタブ) - 私のアプリのほとんどはその中に含まれています。トランジションが 'presentDetail'に変更されました。私はまだスプリットビューコントローラとして比較的うまく動作すると感じていますが、私はUIの専門家ではありません。私は今日の午後にあなたの提案を実装します。再度、感謝します。 – sschale

+0

フォローアップすると、あなたの提案は正しい軌道に乗りました - 私は最終的に私が望むことを達成するために4つの 'delegate'プロパティを実装しなければなりませんでした。それは今(ほぼ)完璧に動作します! – sschale

+0

あなたはそれがうまくいってうれしい! –

関連する問題