问题:当我尝试删除子视图时,应用程序崩溃。
上下文:我有一个UICollectionViewCell,可以使用模型对象进行更新。我已尝试将这些方法放在prepareForReuse
和/或update(model: viewModel)
方法中。
注意:第That view's superview: NO SUPERVIEW
行突出。我甚至在调用removeFromSuperView()
之前将子视图添加回来以确保在superView中存在一些并且它仍然会崩溃。
一旦清除了所有旧的实例,我稍后会重新添加新生成的类timelineView
的实例。
在滚动约50-150个单元格后才会崩溃
更新:感谢您在评论中提供的反馈意见。我没有删除单元格中的所有视图。只有一个堆栈视图,包含可变数量的组件。但你有权删除子视图vs nil'ing out。我更好奇stackView.subviews.first?.removeFromSuperview()
这样的事情是如何失败的,因为它看起来像是一个相对安全的电话(或者我对此错了)。
首先尝试
for subview in stackView.subviews {
subview.removeFromSuperview() // Crash
}
第二次尝试
let subviews = stackView.subviews
for subview in subviews {
if stackView != nil && subview.superview != nil && subview.responds(to: #selector(removeFromSuperview)) && stackView.superview != nil {
stackView.subviews.first?.removeFromSuperview() // Crash
}
}
第三次尝试
let subviews = stackView.subviews
for subview in subviews {
if stackView != nil && subview.superview != nil && subview.responds(to:#selector(removeFromSuperview)) && stackView.superview != nil {
if var firstSubview = stackView.subviews.first {
for constraint in firstSubview.constraints {
constraint.isActive = false
}
stackView.removeArrangedSubview(firstSubview)
firstSubview.removeFromSuperview() // Crash
}
}
}
例外:
2016-12-09 00:56:26.792168 appName[59081:4139912] [LayoutConstraints] View hierarchy unprepared for constraint.
Constraint: <NSLayoutConstraint:0x618000490cc0 'UISV-canvas-connection' UIStackView:0x7fe25cd25dd0.bottom == appName.timeLineView:0x7fe25e007890.bottom (active)>
Container hierarchy:
<UIStackView: 0x7fe25cd25dd0; frame = (0 0; 718 40); opaque = NO; autoresize = RM+BM; layer = <CATransformLayer: 0x6080002295a0>>
View not found in container hierarchy: <appName.timeLineView: 0x7fe25e007890; frame = (0 0; 718 40); autoresize = W+H; layer = <CALayer: 0x610000835c40>>
That view's superview: NO SUPERVIEW
2016-12-09 00:58:38.655 appName[59081:4139912] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal. constraint:<NSLayoutConstraint:0x618000490cc0 'UISV-canvas-connection' UIStackView:0x7fe25cd25dd0.bottom == appName.timeLineView:0x7fe25e007890.bottom (active)> view:<UIStackView: 0x7fe25cd25dd0; frame = (0 0; 718 40); opaque = NO; autoresize = RM+BM; layer = <CATransformLayer: 0x6080002295a0>>'
*** First throw call stack:
(
0 CoreFoundation 0x000000010df0434b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000011215121e objc_exception_throw + 48
2 CoreFoundation 0x000000010df6d265 +[NSException raise:format:] + 197
3 Foundation 0x000000010f097865 -[NSLayoutConstraint _addToEngine:integralizationAdjustment:mutuallyExclusiveConstraints:] + 200
4 Foundation 0x000000010f27c6ed __36-[NSISEngine rebuildFromConstraints]_block_invoke + 208
5 Foundation 0x000000010f09dbd0 -[NSISEngine withBehaviors:performModifications:] + 155
6 Foundation 0x000000010f27c610 -[NSISEngine rebuildFromConstraints] + 488
7 Foundation 0x000000010f0a3e1a -[NSISEngine optimize] + 121
8 Foundation 0x000000010f27c883 -[NSISEngine _optimizeIfNotDisabled] + 57
9 Foundation 0x000000010f0a4ec3 -[NSISEngine removeConstraintWithMarker:] + 799
10 Foundation 0x000000010f09bca8 -[NSLayoutConstraint _removeFromEngine:] + 229
11 UIKit 0x00000001112314a0 -[UIView(UIConstraintBasedLayout) _layoutEngine_willRemoveLayoutConstraint:] + 105
12 UIKit 0x0000000111231bb1 -[UIView(UIConstraintBasedLayout) nsli_removeConstraint:] + 93
13 UIKit 0x0000000111243cef _UIViewRemoveConstraintsMadeDanglyByChangingSuperview + 1016
14 UIKit 0x000000011091965a __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 61
15 UIKit 0x00000001109195a2 -[UIView(Hierarchy) _postMovedFromSuperview:] + 857
16 UIKit 0x000000011091721c __UIViewWasRemovedFromSuperview + 172
17 UIKit 0x0000000110916d13 -[UIView(Hierarchy) removeFromSuperview] + 564
18 appName 0x0000000109aad884 _TFC10appName22TestCollectionViewCell15prepareForReusefT_T_ + 3380
19 appName 0x0000000109aada42 _TToFC10appName22TestCollectionViewCell15prepareForReusefT_T_ + 34
20 UIKit 0x00000001111bee14 -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:] + 561
21 UIKit 0x00000001111bf834 -[UICollectionView dequeueReusableCellWithReuseIdentifier:forIndexPath:] + 169
22 appName 0x0000000109a83623 _TFC10appName30FlightsViewController14collectionViewfTCSo16UICollectionView13cellForItemAtV10Foundation9IndexPath_CSo20UICollectionViewCell + 339
23 appName 0x0000000109a83ca7 _TToFC10appName30FlightsViewController14collectionViewfTCSo16UICollectionView13cellForItemAtV10Foundation9IndexPath_CSo20UICollectionViewCell + 87
24 UIKit 0x00000001111aa980 -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:notify:] + 467
25 UIKit 0x00000001111aa7a7 -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:] + 35
26 UIKit 0x00000001111afc7f -[UICollectionView _updateVisibleCellsNow:] + 4803
27 UIKit 0x00000001111b5913 -[UICollectionView layoutSubviews] + 313
28 UIKit 0x000000011092cf50 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1237
29 QuartzCore 0x00000001102c9cc4 -[CALayer layoutSublayers] + 146
30 QuartzCore 0x00000001102bd788 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
31 QuartzCore 0x00000001102bd606 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
32 QuartzCore 0x000000011024b680 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 280
33 QuartzCore 0x0000000110278767 _ZN2CA11Transaction6commitEv + 475
34 QuartzCore 0x00000001101d3b97 _ZN2CA7Display11DisplayLink14dispatch_itemsEyyy + 611
35 CoreFoundation 0x000000010de96964 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
36 CoreFoundation 0x000000010de965f3 __CFRunLoopDoTimer + 1075
37 CoreFoundation 0x000000010de9617a __CFRunLoopDoTimers + 250
38 CoreFoundation 0x000000010de8df01 __CFRunLoopRun + 2065
39 CoreFoundation 0x000000010de8d494 CFRunLoopRunSpecific + 420
40 GraphicsServices 0x00000001144e9a6f GSEventRunModal + 161
41 UIKit 0x0000000110868964 UIApplicationMain + 159
42 appName 0x0000000109a2ba9f main + 111
43 libdyld.dylib 0x00000001133b468d start + 1
)
谢谢
答案 0 :(得分:0)
有一个类似的问题,我认为我刚刚从stackview中删除项目时非常小心地解决了它 - 这是一个总结它的扩展:
extension UIStackView {
func safelyRemoveArrangedSubviews() {
// Remove all the arranged subviews and save them to an array
let removedSubviews = arrangedSubviews.reduce([]) { (sum, next) -> [UIView] in
self.removeArrangedSubview(next)
return sum + [next]
}
// Deactive all constraints at once
NSLayoutConstraint.deactivate(removedSubviews.flatMap({ $0.constraints }))
// Remove the views from self
removedSubviews.forEach({ $0.removeFromSuperview() })
}
}
答案 1 :(得分:0)
for subview in stackView.subviews {
stackView.removeArrangedSubview(subview)
NSLayoutConstraint.deactivate(subview.constraints)
subview.removeFromSuperview()
}
print("subviews: \(stackView.subviews)")
// subviews: []
答案 2 :(得分:0)
问题与您的视图LayoutConstraints
相关联。
似乎一个名为UISV-canvas-connection
的约束基于您要删除的视图:
2016-12-09 00:56:26.792168 appName[59081:4139912] [LayoutConstraints] View hierarchy unprepared for constraint.
Constraint: <NSLayoutConstraint:0x618000490cc0 'UISV-canvas-connection' UIStackView:0x7fe25cd25dd0.bottom == appName.timeLineView:0x7fe25e007890.bottom (active)>
Container hierarchy:
<UIStackView: 0x7fe25cd25dd0; frame = (0 0; 718 40); opaque = NO; autoresize = RM+BM; layer = <CATransformLayer: 0x6080002295a0>>
View not found in container hierarchy: <appName.timeLineView: 0x7fe25e007890; frame = (0 0; 718 40); autoresize = W+H; layer = <CALayer: 0x610000835c40>>
That view's superview: NO SUPERVIEW
此约束基于不再位于视图层次结构中的UIStackView(因此消息:That view's superview: NO SUPERVIEW
)。
因此从超级视图中删除该约束后,将无法基于该视图评估约束。
答案 3 :(得分:0)
我正在这样做,与3个独立的循环相比,它似乎工作得更好
extension UIStackView {
func removeAllArrangedSubviews() {
arrangedSubviews.forEach {
self.removeArrangedSubview($0)
NSLayoutConstraint.deactivate($0.constraints)
$0.removeFromSuperview()
}
}
}