2016-07-19 9 views
1

Ich entwickle eine App, die iOS 8.0+ mit Swift 2.2 und Realm 1.0.2 als Datenspeicher anvisiert.Absturz in viewWillTransitionToSize

Ich sehe viele Abstürze auf diesen Code in den Crash-Protokolle im Zusammenhang obwohl ich derzeit nicht sie selbst reproduzieren:

/// Resize cells when orientation changes. 
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { 
    if visible { 
     dispatch_async(dispatch_get_main_queue()) { 
      if let coordinator = coordinator as UIViewControllerTransitionCoordinator? { 
       if self.collectionView != nil { 
        self.collectionView.reloadData() 

        coordinator.animateAlongsideTransition({ context in 
         self.collectionView.performBatchUpdates(nil, completion: nil) 
        }, completion: nil) 
       } 
      } 
     } 
    } 
} 

Dieser Code in einem View-Controller erscheint, die eine UICollectionView enthält, die in Zellen zeigt verschiedene Größen je nach Ausrichtung. Ich bin nicht klar, warum ich self.collectionView.reloadData() vor der Animation brauche, aber ohne sie sind die Ränder viel breiter als beabsichtigt.

Hier ist die Spur erhalte ich:

0 libobjc.A.dylib     0x0000000180f400b0 objc_retain + 16 (objc-object.h:341) 
1 UIKit       0x00000001873a1570 -[_UIViewControllerTransitionCoordinator _animateAlongsideTransitionInView:systemCompletion:animation:completion:] + 112 (UIViewControllerTransitioning.m:865) 
2 UIKit       0x0000000186b17f40 -[_UIViewControllerTransitionCoordinator animateAlongsideTransition:completion:] + 68 (UIViewControllerTransitioning.m:906) 
3 MyApp       0x00000001000fc78c 0x1000c0000 + 247692 
4 libdispatch.dylib    0x000000018130d4bc _dispatch_call_block_and_release + 24 (init.c:760) 
5 libdispatch.dylib    0x000000018130d47c _dispatch_client_callout + 16 (object.m:506) 
6 libdispatch.dylib    0x0000000181312b84 _dispatch_main_queue_callback_4CF + 1844 (inline_internal.h:1063) 
7 CoreFoundation     0x0000000181878d50 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12 (CFRunLoop.c:1613) 
8 CoreFoundation     0x0000000181876bb8 __CFRunLoopRun + 1628 (CFRunLoop.c:2718) 
9 CoreFoundation     0x00000001817a0c50 CFRunLoopRunSpecific + 384 (CFRunLoop.c:2814) 
10 GraphicsServices    0x0000000183088088 GSEventRunModal + 180 (GSEvent.c:2245) 
11 UIKit       0x0000000186a82088 UIApplicationMain + 204 (UIApplication.m:3772) 
12 MyApp       0x00000001000c92d8 0x1000c0000 + 37592 
13 libdyld.dylib     0x000000018133e8b8 start + 4 (start_glue.s:78) 

I, indem die Ausrichtung auf einen anderen Bildschirm einen ähnlichen Absturz in der Lage verwenden auszulösen und dann kommt schnell wieder auf den mit dem UICollectionView. Die if visible Prüfung scheint das zu beheben und ich bekomme viel weniger von diesen Abstürzen, aber immer noch einige. Irgendwelche Ideen, wo nach Problemen in meinem Code gesucht werden oder Ressourcen zum Lesen dieser Spuren würden sehr geschätzt werden.

+2

Warum haben Sie den GCD-Aufruf, um Ihren Block auf den Hauptthread zu setzen? Ich glaube, 'viewWillTransitionToSize' (wie andere UIKit-Methoden) wird im Hauptthread aufgerufen. Ich bin mir nicht sicher, ob das Ihren Absturz verursachen könnte. – dylansturg

+0

@DylanS Das und ein paar andere, wahrscheinlich unnötige Dinge sind wegen Vorschlägen, die ich gefunden habe, auf der Suche nach dem Problem. Mein Verständnis ist, dass, wenn es bereits auf dem Hauptthread ist, das 'dispatch_async' nur überflüssig ist, aber nicht tut weh. –

+1

10 Das kann oder darf nicht wahr sein. Angenommen, Apple hat 'viewWillTransitionToSize' so implementiert, dass nach der Rückkehr alle Änderungen an 'coordinator' ungültig oder instabil sind. Da Ihr Code in einen Block verpackt ist, der an GCD gesendet wird, wird 'viewWillTransitionToSize' zurückgeliefert, bevor Ihr Block ausgeführt wird (manchmal verspricht GCD nur, in der gegebenen Warteschlange zu laufen, aber nicht wirklich irgendwelche Versprechen bezüglich der Bestellung). Zum Beispiel, wenn der View-Controller seine Animationen startet ... Dann führt GCD Ihren Block aus ... Wie könnte er auf den Empfang zusätzlicher Animationen in der Mitte reagieren? Es ist möglicherweise nicht definiert. – dylansturg

Antwort

3

Es gibt ein paar kleine Probleme hier:

  • rufen immer super in UIViewController Lifecycle-Methoden
  • Die GCD Anruf kann zu unerwarteten Inkonsistenzen führen

Beachten Sie, dass dispatch_async nur Pläne Code Block mit GCD und gibt keine Garantien darüber, wann es ausgeführt wird. Es ist durchaus möglich, dass dieser Block nach dem Start der Animationen ausgeführt wird und der Größenübergang in einem inkonsistenten Zustand bleibt.