2017-09-25 18 views
5

Tôi có một phiên bản UINavigationController được lồng trong UITabBarController. Tôi sử dụng bộ điều khiển điều hướng để tiếp cận với một số bộ điều khiển xem (thanh tab vẫn còn nhìn thấy được), từ đó tôi chuyển sang bộ điều khiển xem thứ hai (thanh tab không còn nhìn thấy được).Phương pháp UINavigationController setToolbarHidden lỗi trong Xcode 9: tính toán vô hạn các ràng buộc bố cục tự động dẫn đến OOM

Trong trình điều khiển chế độ xem thứ hai, ngay sau khi tôi thực hiện cuộc gọi đến: [self.navigationController setToolbarHidden:NO] ứng dụng bị đóng băng và bộ nhớ phát triển cho đến khi ngoại lệ OOM gặp sự cố.

Tôi xác nhận rằng làm tổ bộ điều khiển chuyển hướng bên trong thanh tab không được khuyến khích, nhưng thiết lập này dường như làm việc tốt cho đến khi iOS 11.

EDIT: khi dừng thực hiện, tôi thấy rất nhiều cuộc gọi đến:

UIView(UIConstraintBasedLayout)

UIView(AdditionalLayerSupport)

NSLayoutConstraint

Dưới đây là stack đầy đủ dấu vết

* 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 

Trả lời

3

Đây là câu trả lời từ một nhà phát triển từ nhóm giống như OP là từ.

Sau hơn một vòng nghiên cứu, chúng tôi đã phát hiện ra rằng vấn đề là về phía chúng tôi:

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

gốc nhà phát triển đưa ra phương pháp toolbarItemsWithRunningAdditionalAnimation để trở về đối tượng mới mỗi lần phương pháp này được gọi. Khi đi đến bộ điều khiển này, iOS gọi toolbarItems ít nhất 3 lần để cho nó đối tượng mới mỗi lần chúng tôi làm iOS bối rối nên nó tính toán lại các ràng buộc bố trí tự động trong một vòng lặp vô hạn. sửa chữa ban đầu của chúng tôi dưới đây cũng đang làm việc, tuy nhiên nó trở nên lỗi thời khi chúng ta bắt đầu luôn luôn trở về cùng một mảng các mặt hàng như:

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

    _cachedToolbarItems = [self toolbarItemsWithRunningAdditionalAnimation:NO]; 

    return _cachedToolbarItems' 
} 

Chúng tôi đang làm như sau trong ứng dụng của chúng tôi (giả):

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

Các mục có vấn đề gây ra tính toán vô hạn các ràng buộc bố cục tự động là sharestats. Cả hai đều có điểm chung - cả hai đều được tạo bằng cách sử dụng bộ khởi tạo -[UIBarButtonItem initWithImage:style:target:action:]. Khi chúng tôi bắt đầu sử dụng trình khởi tạo khác:

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

Sự cố đã biến mất.

2

Bên cạnh câu trả lời được chấp nhận, chúng tôi nhận thấy rằng vấn đề của chúng tôi liên quan đến thực tế là trong lớp học của chúng tôi, chúng tôi ghi đè phương thức - (NSArray *)toolbarItems.

Mỗi lần phương thức của chúng tôi được gọi, một bộ toolbarItem mới được tạo. Dường như từ iOS 11, mỗi lần mới mục thanh công cụ mới được trả về phương thức này, UINavigationController:layoutIfNeeded được gọi lại, lần lượt gọi toolbarItems trả về các mục mới do triển khai của chúng tôi. Điều này gây ra một vòng lặp vô hạn.

Nếu bạn gặp sự cố này, hãy kiểm tra xem bạn có ghi đè - (NSArray *)toolbarItems

Các vấn đề liên quan