2017-09-25 1 views
5

인스턴스가 UITabBarController에 중첩 된 UINavigationController입니다. 탐색 컨트롤러를 사용하여 일부보기 컨트롤러 (탭 표시 줄이 여전히 표시됨)에 도달 한 후 두 번째보기 컨트롤러 (더 이상 표시되지 않는 탭 표시 줄)로 연결됩니다. 두 번째 뷰 컨트롤러에서 UINavigationController 메서드 Xcode 9의 setToolbarHidden 버그 : 자동 레이아웃 제약 조건의 무한 계산으로 인해 OOM이 발생합니다

는 최대한 빨리로 전화를 걸 같이 OOM 예외가 충돌 할 때까지 [self.navigationController setToolbarHidden:NO] 응용 프로그램 동결 및 메모리 성장한다.

내가 탭 표시 줄의 내부 탐색 컨트롤러를 중첩하는 것은 권장되지 않습니다 것을 인정하지만,이 설정은 아이폰 OS까지 잘 작동하는 것 같았다 (11)

편집 : 실행을 중지 할 때, 나는 호출을 많이 참조 :

UIView(UIConstraintBasedLayout)

UIView(AdditionalLayerSupport)

NSLayoutConstraint

여기이 영업 이익에서와 같이 같은 팀에서 개발자의 대답은 전체 스택 추적

* 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 

답변

3

입니다.

연구의 또 하나의 라운드 후 우리는 문제가 우리의 편에 있음을 발견했다 :

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

원래 개발자가 새로운 객체에게 메서드가 호출 될 때마다 반환하는 방법 toolbarItemsWithRunningAdditionalAnimation했다. 이 컨트롤러로 갈 때 iOS는 최소 3 번 toolbarItems을 호출하므로 iOS를 혼란스럽게 만들 때마다 새로운 객체를 부여하므로 무한 루프에서 자동 레이아웃 제약 조건을 다시 계산합니다. 우리는 항상 같은 항목의 동일한 배열을 반환 시작하면 아래도하고있다 우리의 원래 수정, 그러나 그것은 더 이상 사용되지 :

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

    _cachedToolbarItems = [self toolbarItemsWithRunningAdditionalAnimation:NO]; 

    return _cachedToolbarItems' 
} 

우리는 (의사) 우리의 응용 프로그램에서 다음을 수행됩니다

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]; 

자동 레이아웃 제한 조건을 무한히 계산하는 문제가있는 항목은 sharestats입니다. 둘 다 공통점이 있었는데 둘 다 -[UIBarButtonItem initWithImage:style:target:action:] 이니셜 라이저를 사용하여 만들었습니다. 다른 초기화 프로그램을 사용할 때 :

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

문제가 해결되었습니다.

2

대답에 더하여, 우리의 문제는 우리 클래스에서 - (NSArray *)toolbarItems 메서드를 오버라이드한다는 사실과 관련이 있다는 것을 발견했습니다.

우리의 메서드가 호출 될 때마다 새로운 toolbarItem 세트가 만들어집니다. iOS 11과 같아서 개의 새로운 툴바 항목이이 메소드에 반환 될 때마다 UINavigationController:layoutIfNeeded이 다시 호출되며, 이는 구현 때문에 새로운 항목을 반환하는 toolbarItems을 호출합니다. 이로 인해 무한 루프가 발생합니다.

이 문제가 발생하면 - (NSArray *)toolbarItems

을 무시하고 있는지 확인하십시오.
관련 문제