ios - iPhone 6 Plus UISplitViewController crash with recursive _canBecomeDeepestUnambiguousResponder -


i have existing iphone app i'm adding uisplitviewcontroller to. ipad part works charm, i'm having guaranteed crash iphone 6(s) plus.

setup - master uitabbarcontroller. initial detail view placeholder logo view. once object selected, detail replaced uitabbarcontroller.

whenever select item , open detail in iphone 6 plus , rotate portrait (detail visible) landscape (where master visible), crashes. not occur on rotation placeholder detail view.

before crash, call delegate methods primaryviewcontrollerforexpandingsplitviewcontroller , splitviewcontroller(splitviewcontroller: uisplitviewcontroller, separatesecondaryviewcontrollerfromprimaryviewcontroller. however, works fine on ipad.

i've done ton of searching , seen couple twitter mentions of type of crash. things setting or not setting displaymodebuttonitem don't help.

i recreated crash in fresh project - can downloaded here: https://github.com/sschale/splitviewcrash/

crash log:

crashed thread:        0  dispatch queue: com.apple.main-thread  exception type:        exc_bad_access (sigsegv) exception codes:       kern_protection_failure @ 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 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 

this crashes on ipad too. use multitasking resize app compact width (e.g. 1/3rd screen), press launch detail button, resize regular width.

when you're in compact width, split view controller "collapsed". means no longer shows separate primary , secondary view controllers @ same time -- instead, "collapses" them single view controller hierarchy. when it's in environment, needs in order act sensibly. default behavior works when both primary , secondary view controllers uinavigationcontrollers, not in other cases.

(in app, primary uitabbarcontroller, , after "launch detail" once, secondary uitabbarcontroller. may want reconsider design, because makes things more difficult. keep reading.)

your app's "launch detail" button performs "show detail" segue, calls method on uisplitviewcontroller:

public func showdetailviewcontroller(vc: uiviewcontroller, sender: anyobject?) 

note comment in header:

// in horizontally-compact environment master view controller // or detail view controller sent showviewcontroller:sender: // message. if neither 1 of them provide implementation // method fall full screen presentation. 

by "master view controller or detail view controller", means view controller shown, in case uitabbarcontroller. uitabbarcontroller not implement showviewcontroller() because doesn't have enough information -- show view controller? add new tab, or replace old one, or what?

so, result, fallback, full-screen presentation. doubt want user experience.

later on, when size changes regular , split view controller expands, gets confused presentation , crashes. (see mean defaults not being good?)

one way fix implement delegate method handle showdetail. when width compact, explicitly find view controller want put new view controller onto, , it. think want push onto nav controller in first tab:

func splitviewcontroller(splitviewcontroller: uisplitviewcontroller, showdetailviewcontroller vc: uiviewcontroller, sender: anyobject?) -> bool {     if splitviewcontroller.traitcollection.horizontalsizeclass == .compact {         // default implementation not handle properly.         // find appropriate navigation controller , push onto it.         // better have direct outlet appropriate navigation controller,          // work example...          if let tabbarcontroller = splitviewcontroller.viewcontrollers.first as? uitabbarcontroller {             if let navcontroller = tabbarcontroller.viewcontrollers?.first as? uinavigationcontroller {                 navcontroller.pushviewcontroller(vc, animated: true)                  // handled "show detail", split view controller,                  // please don't else                 return true             }         }     }      // did not handle "show detail", split view controller,      // please default behavior     return false } 

if that, want implement delegate method. when size changed regular, want handle "expand" popping view controller off of same nav controller, returning it:

optional public func splitviewcontroller(     splitviewcontroller: uisplitviewcontroller     separatesecondaryviewcontrollerfromprimaryviewcontroller         primaryviewcontroller: uiviewcontroller) -> uiviewcontroller? 

Popular posts from this blog

php - How should I create my API for mobile applications (Needs Authentication) -

5 Reasons to Blog Anonymously (and 5 Reasons Not To)

Google AdWords and AdSense - A Dynamic Small Business Marketing Duo