- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我有一个 UINavigationController
实例嵌套在 UITabBarController
中。我使用导航 Controller 到达某个 View Controller (标签栏仍然可见),我从那里转到第二个 View Controller (标签栏不再可见)。
在第二个 View Controller 中,只要我调用:[self.navigationController setToolbarHidden:NO]
应用程序卡住并且内存增长,直到 OOM 异常使其崩溃。
我承认不建议将导航 Controller 嵌套在标签栏内,但在 iOS 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
最佳答案
这是来自与 OP 来自同一团队的开发人员的回答。
经过又一轮的研究,我们发现问题出在我们这边:
- (NSArray *)toolbarItems
{
return [self toolbarItemsWithRunningAdditionalAnimation:NO];
}
原始开发人员制作方法 toolbarItemsWithRunningAdditionalAnimation
以在每次调用该方法时返回新对象。当转到此 Controller 时,iOS 至少调用 toolbarItems
3 次,因此每次我们让 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];
导致无限计算自动布局约束的问题项是 share
和 stats
。它们的共同点是——它们都是使用 -[UIBarButtonItem initWithImage:style:target:action:]
初始化器创建的。当我们开始使用另一个初始化器时:
UIButton *customShareButton = ... // we create button ourselves.
UIBarButtonItem *shareItem = [[UIBarButtonItem alloc] initWithCustomView: customShareButton];
问题消失了。
关于ios - Xcode 9 : infinite calculation of auto-layout constraints leads to OOM 中的 UINavigationController 方法 setToolbarHidden 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46409420/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!