2017-09-25 1 views
5

Ich habe eine Instanz von UINavigationController verschachtelt in UITabBarController. Ich benutze den Navigationscontroller, um einen View-Controller zu erreichen (Tab-Leiste noch sichtbar), von dem ich zu einem zweiten View-Controller übergehe (Tab-Leiste nicht mehr sichtbar).UINavigationController-Methode setToolbarHidden Fehler in Xcode 9: unendliche Berechnung von Auto-Layout-Einschränkungen führt zu OOM

In den zweiten View-Controller, sobald ich einen Anruf zu tätigen: [self.navigationController setToolbarHidden:NO] die App gefrieren und Speicher wächst, bis OOM Ausnahme stürzt.

Ich nehme zur Kenntnis, dass in der Tab-Leiste die Navigationssteuerung Verschachtelung wird nicht empfohlen, aber das Setup schien, bis iOS zu funktionieren 11.

EDIT:, wenn die Ausführung zu stoppen, habe ich eine Menge Anrufe sehen:

UIView(UIConstraintBasedLayout)

UIView(AdditionalLayerSupport)

NSLayoutConstraint

Hier ist der volle Stack-Trace

* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP * frame #0: 0x0000000106dd895c libobjc.A.dylib`objc_msgSend 
+ 28 
    frame #1: 0x00000001067b6b9b Foundation`-[NSConcreteMapTable removeObjectForKey:] + 138 
    frame #2: 0x00000001069e6019 Foundation`_substituteOutAllOccurencesOfBodyVar + 1282 
    frame #3: 0x00000001067f3c5b Foundation`-[NSISEngine tryAddingDirectly:] + 144 
    frame #4: 0x00000001067f332f Foundation`-[NSISEngine tryToAddConstraintWithMarker:expression:integralizationAdjustment:mutuallyExclusiveConstraints:] 
+ 440 
    frame #5: 0x00000001069f2067 Foundation`-[NSLayoutConstraint _addLoweredExpression:toEngine:integralizationAdjustment:lastLoweredConstantWasRounded:mutuallyExclusiveConstraints:] 
+ 273 
    frame #6: 0x00000001067ea601 Foundation`-[NSLayoutConstraint _addToEngine:integralizationAdjustment:mutuallyExclusiveConstraints:] + 240 
    frame #7: 0x0000000109c9488d UIKit`__57-[UIView(AdditionalLayoutSupport) 
_switchToLayoutEngine:]_block_invoke_2 + 452 
    frame #8: 0x00000001067f0de1 Foundation`-[NSISEngine withBehaviors:performModifications:] + 131 
    frame #9: 0x0000000109c946a2 UIKit`__57-[UIView(AdditionalLayoutSupport) 
_switchToLayoutEngine:]_block_invoke + 604 
    frame #10: 0x0000000109c9441e UIKit`-[UIView(AdditionalLayoutSupport) _switchToLayoutEngine:] + 223 
    frame #11: 0x00000001091ed84f UIKit`__45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 112 
    frame #12: 0x00000001067f0de1 Foundation`-[NSISEngine withBehaviors:performModifications:] + 131 
    frame #13: 0x00000001091ed778 UIKit`-[UIView(Hierarchy) _postMovedFromSuperview:] + 855 
    frame #14: 0x00000001091fe031 UIKit`-[UIView(Internal) _addSubview:positioned:relativeTo:] + 1927 
    frame #15: 0x0000000109b507e1 UIKit`-[_UILayoutArrangement insertItem:atIndex:] + 502 
    frame #16: 0x0000000109ca1b4d UIKit`__50-[_UIOrderedLayoutArrangement insertItem:atIndex:]_block_invoke + 50 
    frame #17: 0x0000000109ca18df UIKit`-[_UIOrderedLayoutArrangement _trackChangesAffectingExternalBaselineConstraints:] + 320 
    frame #18: 0x0000000109ca1aea UIKit`-[_UIOrderedLayoutArrangement insertItem:atIndex:] + 478 
    frame #19: 0x000000010982edea UIKit`-[UIStackView insertArrangedSubview:atIndex:] + 283 
    frame #20: 0x0000000109b29972 UIKit`-[_UIButtonBar _layoutBar] + 3639 
    frame #21: 0x0000000109b2bb44 UIKit`-[_UIButtonBarStackView updateConstraints] + 48 
    frame #22: 0x0000000109c958b6 UIKit`-[UIView(AdditionalLayoutSupport) 
_sendUpdateConstraintsIfNecessaryForSecondPass:] + 161 
    frame #23: 0x0000000109c95ed2 UIKit`-[UIView(AdditionalLayoutSupport) 
_updateConstraintsIfNeededCollectingViews:forSecondPass:] + 1296 
    frame #24: 0x0000000109c95d51 UIKit`-[UIView(AdditionalLayoutSupport) 
_updateConstraintsIfNeededCollectingViews:forSecondPass:] + 911 
    frame #25: 0x0000000109c95d51 UIKit`-[UIView(AdditionalLayoutSupport) 
_updateConstraintsIfNeededCollectingViews:forSecondPass:] + 911 
    frame #26: 0x0000000109c95d51 UIKit`-[UIView(AdditionalLayoutSupport) 
_updateConstraintsIfNeededCollectingViews:forSecondPass:] + 911 
    frame #27: 0x00000001067f0de1 Foundation`-[NSISEngine withBehaviors:performModifications:] + 131 
    frame #28: 0x0000000109c96703 UIKit`__100-[UIView(AdditionalLayoutSupport) 
_updateConstraintsIfNeededWithViewForVariableChangeNotifications:]_block_invoke 
+ 90 
    frame #29: 0x0000000109c94f61 UIKit`-[UIView(AdditionalLayoutSupport) 
_withUnsatisfiableConstraintsLoggingSuspendedIfEngineDelegateExists:] + 104 
    frame #30: 0x0000000109c96272 UIKit`-[UIView(AdditionalLayoutSupport) 
_updateConstraintsIfNeededWithViewForVariableChangeNotifications:] + 160 
    frame #31: 0x0000000109c9738c UIKit`-[UIView(AdditionalLayoutSupport) 
_updateConstraintsAtEngineLevelIfNeededWithViewForVariableChangeNotifications:] 
+ 401 
    frame #32: 0x00000001091ef1b6 UIKit`-[UIView(Hierarchy) layoutBelowIfNeeded] + 1517 
    frame #33: 0x000000010957b35e UIKit`-[_UIButtonBarButton willMoveToWindow:] + 63 
    frame #34: 0x00000001091ec996 UIKit`-[UIView(Hierarchy) _willMoveToWindow:] + 861 
    frame #35: 0x00000001091eb493 UIKit`__UIViewWillBeRemovedFromSuperview + 484 
    frame #36: 0x00000001091eb0ea UIKit`-[UIView(Hierarchy) removeFromSuperview] + 95 
    frame #37: 0x0000000109b295d3 UIKit`-[_UIButtonBar _layoutBar] + 2712 
    frame #38: 0x0000000109b2bb44 UIKit`-[_UIButtonBarStackView updateConstraints] + 48 
    frame #39: 0x0000000109c958b6 UIKit`-[UIView(AdditionalLayoutSupport) 
_sendUpdateConstraintsIfNecessaryForSecondPass:] + 161 
    frame #40: 0x0000000109c95ed2 UIKit`-[UIView(AdditionalLayoutSupport) 
_updateConstraintsIfNeededCollectingViews:forSecondPass:] + 1296 
    frame #41: 0x0000000109c95d51 UIKit`-[UIView(AdditionalLayoutSupport) 
_updateConstraintsIfNeededCollectingViews:forSecondPass:] + 911 
    frame #42: 0x0000000109c95d51 UIKit`-[UIView(AdditionalLayoutSupport) 
_updateConstraintsIfNeededCollectingViews:forSecondPass:] + 911 
    frame #43: 0x0000000109c95d51 UIKit`-[UIView(AdditionalLayoutSupport) 
_updateConstraintsIfNeededCollectingViews:forSecondPass:] + 911 
    frame #44: 0x00000001067f0de1 Foundation`-[NSISEngine withBehaviors:performModifications:] + 131 
    frame #45: 0x0000000109c96703 UIKit`__100-[UIView(AdditionalLayoutSupport) 
_updateConstraintsIfNeededWithViewForVariableChangeNotifications:]_block_invoke 
+ 90 
    frame #46: 0x0000000109c94f61 UIKit`-[UIView(AdditionalLayoutSupport) 
_withUnsatisfiableConstraintsLoggingSuspendedIfEngineDelegateExists:] + 104 
    frame #47: 0x0000000109c96272 UIKit`-[UIView(AdditionalLayoutSupport) 
_updateConstraintsIfNeededWithViewForVariableChangeNotifications:] + 160 
    frame #48: 0x0000000109c9738c UIKit`-[UIView(AdditionalLayoutSupport) 
_updateConstraintsAtEngineLevelIfNeededWithViewForVariableChangeNotifications:] 
+ 401 
    frame #49: 0x00000001091efa5b UIKit`-[UIView(Hierarchy) _updateConstraintsAsNecessaryAndApplyLayoutFromEngine] + 159 
    frame #50: 0x00000001095742d5 UIKit`-[UILayoutContainerView layoutSubviews] + 270 
    frame #51: 0x0000000109204551 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1331 
    frame #52: 0x00000001064db4ba QuartzCore`-[CALayer layoutSublayers] + 153 
    frame #53: 0x00000001064df5a9 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 401 
    frame #54: 0x00000001064681cd QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 365 
    frame #55: 0x0000000106493ae4 QuartzCore`CA::Transaction::commit() + 500 
    frame #56: 0x0000000109160687 UIKit`_afterCACommitHandler + 272 
    frame #57: 0x00000001080f8db7 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ 
+ 23 
    frame #58: 0x00000001080f8d0e CoreFoundation`__CFRunLoopDoObservers + 430 
    frame #59: 0x00000001080dd324 CoreFoundation`__CFRunLoopRun + 1572 
    frame #60: 0x00000001080dca89 CoreFoundation`CFRunLoopRunSpecific + 409 
    frame #61: 0x000000010dc429c6 GraphicsServices`GSEventRunModal + 62 
    frame #62: 0x0000000109135d30 UIKit`UIApplicationMain + 159 
    frame #63: 0x0000000101ff6bf9 MyAppName`main(argc=1, argv=0x00007fff5de3e0a8) at main.m:23 
    frame #64: 0x000000010f453d81 libdyld.dylib`start + 1 
    frame #65: 0x000000010f453d81 libdyld.dylib`start + 1 

Antwort

3

Dies ist die Antwort von einem Entwickler aus dem gleichen Team wie OP aus ist.

Nach einer weiteren Runde der Forschung haben wir herausgefunden, dass das Problem auf unserer Seite war:

- (NSArray *)toolbarItems 
{ 
    return [self toolbarItemsWithRunningAdditionalAnimation:NO]; 
} 

Original-Entwickler die Methode toolbarItemsWithRunningAdditionalAnimation neue Objekte jedes Mal, wenn die Methode aufgerufen wurde zurückgeführt. Wenn ich zu diesem Controller gehe, ruft iOS mindestens 3 mal toolbarItems an, so dass es jedes Mal, wenn wir iOS durcheinander brachten, neue Objekte gab, so dass Auto-Layout-Einschränkungen in einer Endlosschleife neu berechnet wurden. Unsere ursprüngliche Update unten auch funktioniert, jedoch wird es überflüssig, da wir beginnen immer die gleiche Anordnung von Elementen wie eine Rückkehr:

- (NSArray *)toolbarItems { 
    if (_cachedToolbarItems) { return _cachedToolbarItems; } 

    _cachedToolbarItems = [self toolbarItemsWithRunningAdditionalAnimation:NO]; 

    return _cachedToolbarItems' 
} 

Wir tun das folgende in unserer App (Pseudo-Code):

UIToolbar *toolbar = self.navigationController.toolbar; 

NSArray <UIBarButtonItem *> *items = @[ 
    flexibleSpace, 
    share, 
    flexibleSpace, 
    play, 
    flexibleSpace, 
    stats, 
    flexibleSpace 
]; 
[toolbar setItems:items animated:animated]; 

[self.navigationController setToolbarHidden:NO animated:animated]; 

Die problematischen Elemente, die eine unendliche Berechnung von Auto-Layout-Einschränkungen verursachten, waren share und stats. Die Sache, die sie beide gemeinsam hatten - sie beide wurden mit -[UIBarButtonItem initWithImage:style:target:action:] Initialisierer erstellt. Als wir anfingen, einen anderen Initialisierer zu verwenden:

UIButton *customShareButton = ... // we create button ourselves. 
UIBarButtonItem *shareItem = [[UIBarButtonItem alloc] initWithCustomView: customShareButton]; 

Das Problem ging weg.

2

Neben der akzeptierten Antwort fanden wir, dass unser Problem mit der Tatsache verbunden wurde, dass in unserer Klasse, wir die Methode - (NSArray *)toolbarItems außer Kraft setzen.

Jedes Mal, wenn unsere Methode aufgerufen wird, wird eine neue Gruppe von ToolbarItems erstellt. Scheint wie von iOS 11, jedes Mal, neue Symbolleiste Elemente werden zu dieser Methode zurückgegeben, UINavigationController:layoutIfNeeded wird erneut aufgerufen, die wiederum ruft toolbarItems, die neue Elemente wegen unserer Implementierung zurückgibt. Dies verursacht eine Endlosschleife.

Wenn dieses Problem auftritt, überprüfen Sie, ob Sie die - (NSArray *)toolbarItems

überschreiben