tableView 内的 UIDatePicker 更新无效,在 iOS 13 旋转时崩溃
Invalid update of a UIDatePicker inside tableView crashing in iOS 13 on rotation
我正在添加一个 UIDatePicker 作为 table 的页脚。我有另一个 UITableView 扩展,它实现了 traitCollectionDidChange 并且只执行 beginUpdates 和 endUpdates。我在更改方向时遇到以下崩溃。
*** Assertion failure in -[UIPickerTableView _Bug_Detected_In_Client_Of_UITableView_Invalid_Number_Of_Rows_In_Section:],
/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore_Sim/UIKit-3901.4.2/UITableView.m:2407
2020-05-12 13:35:28.729340+0530 MyApplication[41892:1575639] *** Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0.
The number of rows contained in an existing section after the update (0) must be equal to the number of
rows contained in that section before the update (10000), plus or minus the number of rows inserted or
deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into
or out of that section (0 moved in, 0 moved out).'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff23c7127e __exceptionPreprocess + 350
1 libobjc.A.dylib 0x00007fff513fbb20 objc_exception_throw + 48
2 CoreFoundation 0x00007fff23c70ff8 +[NSException raise:format:arguments:] + 88
3 Foundation 0x00007fff256e9b51 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 191
4 UIKitCore 0x00007fff4825d508 -[UITableView _Bug_Detected_In_Client_Of_UITableView_Invalid_Number_Of_Rows_In_Section:] + 193
5 UIKitCore 0x00007fff4825cdc1 -[UITableView _endCellAnimationsWithContext:] + 16657
6 UIKitCore 0x00007fff48276e0b -[UITableView endUpdatesWithContext:] + 112
7 MyApplication 0x0000000103d13ed1 -[UITableView(RIAdditions) traitCollectionDidChange:] + 97
8 UIKitCore 0x00007fff4854ccc4 -[UIView _traitCollectionDidChangeInternal:] + 977
9 UIKitCore 0x00007fff4854d5c4 -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 161
10 UIKitCore 0x00007fff4854d80a -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 743
11 UIKitCore 0x00007fff4854d80a -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 743
12 UIKitCore 0x00007fff4854d80a -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 743
13 UIKitCore 0x00007fff4854d80a -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 743
14 UIKitCore 0x00007fff4854d80a -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 743
15 UIKitCore 0x00007fff4854d7ae -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 651
16 UIKitCore 0x00007fff4854d935 -[UIView _processDidChangeRecursivelyFromOldTraits:toCurrentTraits:forceNotification:] + 140
17 UIKitCore 0x00007fff485783d2 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2243
18 QuartzCore 0x00007fff2b131db1 -[CALayer layoutSublayers] + 255
19 QuartzCore 0x00007fff2b137fa3 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 517
20 UIKitCore 0x00007fff48563635 -[UIView(Hierarchy) layoutBelowIfNeeded] + 980
21 UIKitCore 0x00007fff47978038 -[UINavigationController _layoutViewController:] + 1465
22 UIKitCore 0x00007fff479710e9 -[UINavigationController _layoutTopViewControllerLookForNested:] + 589
23 UIKitCore 0x00007fff47966e9a __105-[UINavigationController _repositionPaletteWithNavigationBarHidden:duration:shouldUpdateNavigationItems:]_block_invoke + 718
24 UIKitCore 0x00007fff47966b9c -[UINavigationController _repositionPaletteWithNavigationBarHidden:duration:shouldUpdateNavigationItems:] + 308
25 UIKitCore 0x00007fff47970339 -[UINavigationController _updateBarsForCurrentInterfaceOrientationAndForceBarLayout:] + 174
26 UIKitCore 0x00007fff47980763 __84-[UINavigationController willTransitionToTraitCollection:withTransitionCoordinator:]_block_invoke + 639
27 UIKitCore 0x00007fff47a42124 -[_UIViewControllerTransitionCoordinator _applyBlocks:releaseBlocks:] + 294
28 UIKitCore 0x00007fff47a3e446 -[_UIViewControllerTransitionContext __runAlongsideAnimations] + 263
29 UIKitCore 0x00007fff4856bde6 +[UIView(UIViewAnimationWithBlocks) _setupAnimationWithDuration:delay:view:options:factory:animations:start:animationStateGenerator:completion:] + 528
30 UIKitCore 0x00007fff4856c395 +[UIView(UIViewAnimationWithBlocks) animateWithDuration:delay:options:animations:completion:] + 99
31 UIKitCore 0x00007fff47a5665a __58-[_UIWindowRotationAnimationController animateTransition:]_block_invoke_2 + 278
32 UIKitCore 0x00007fff4856ff44 +[UIView(Internal) _performBlockDelayingTriggeringResponderEvents:forScene:] + 174
33 UIKitCore 0x00007fff47a563e8 __58-[_UIWindowRotationAnimationController animateTransition:]_block_invoke + 164
34 UIKitCore 0x00007fff4856bde6 +[UIView(UIViewAnimationWithBlocks) _setupAnimationWithDuration:delay:view:options:factory:animations:start:animationStateGenerator:completion:] + 528
35 UIKitCore 0x00007fff4856c395 +[UIView(UIViewAnimationWithBlocks) animateWithDuration:delay:options:animations:completion:] + 99
36 UIKitCore 0x00007fff47a562c0 -[_UIWindowRotationAnimationController animateTransition:] + 491
37 UIKitCore 0x00007fff480d2e9d -[UIWindow _rotateToBounds:withAnimator:transitionContext:] + 525
38 UIKitCore 0x00007fff480d58e0 -[UIWindow _rotateWindowToOrientation:updateStatusBar:duration:skipCallbacks:] + 2331
39 UIKitCore 0x00007fff480d5ed3 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] + 633
40 UIKitCore 0x00007fff480d4e27 -[UIWindow _setRotatableViewOrientation:updateStatusBar:duration:force:] + 119
41 UIKitCore 0x00007fff480d3ca4 __57-[UIWindow _updateToInterfaceOrientation:duration:force:]_block_invoke + 111
42 UIKitCore 0x00007fff480d3bcd -[UIWindow _updateToInterfaceOrientation:duration:force:] + 455
43 CoreFoundation 0x00007fff23b9b5bc __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
44 CoreFoundation 0x00007fff23b9aa35 _CFXRegistrationPost1 + 421
45 CoreFoundation 0x00007fff23b9a7a1 ___CFXNotificationPost_block_invoke + 193
46 CoreFoundation 0x00007fff23c988b3 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1811
47 CoreFoundation 0x00007fff23b9a0f6 _CFXNotificationPost + 950
48 Foundation 0x00007fff2574bbf7 -[NSNotificationCenter postNotificationName:object:userInfo:] + 59
49 UIKitCore 0x00007fff47cd5955 -[UIDevice setOrientation:animated:] + 224
50 UIKitCore 0x00007fff477c83f1 __134-[_UIWindowSceneDeviceOrientationSettingsDiffAction _updateDeviceOrientationWithSettingObserverContext:windowScene:transitionContext:]_block_invoke + 137
51 UIKitCore 0x00007fff47bd8c83 +[BSAnimationSettings(UIKit) tryAnimatingWithSettings:actions:completion:] + 865
52 UIKitCore 0x00007fff47cd2dff _UISceneSettingsDiffActionPerformChangesWithTransitionContext + 240
53 UIKitCore 0x00007fff477c8336 -[_UIWindowSceneDeviceOrientationSettingsDiffAction _updateDeviceOrientationWithSettingObserverContext:windowScene:transitionContext:] + 248
54 UIKitCore 0x00007fff477c8231 __163-[_UIWindowSceneDeviceOrientationSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:]_block_invoke + 112
55 UIKitCore 0x00007fff47cd2d02 _UISceneSettingsDiffActionPerformActionsWithDelayForTransitionContext + 84
56 UIKitCore 0x00007fff477c80c1 -[_UIWindowSceneDeviceOrientationSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:] + 216
57 UIKitCore 0x00007fff476206e7 __64-[UIScene scene:didUpdateWithDiff:transitionContext:completion:]_block_invoke + 657
58 UIKitCore 0x00007fff4761f26c -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:] + 248
59 UIKitCore 0x00007fff47620411 -[UIScene scene:didUpdateWithDiff:transitionContext:completion:] + 210
60 UIKitCore 0x00007fff47bfac66 -[UIApplicationSceneClientAgent scene:handleEvent:withCompletion:] + 504
61 FrontBoardServices 0x00007fff365d6c07 -[FBSSceneImpl updater:didUpdateSettings:withDiff:transitionContext:completion:] + 565
62 FrontBoardServices 0x00007fff365fc99f __88-[FBSWorkspaceScenesClient sceneID:updateWithSettingsDiff:transitionContext:completion:]_block_invoke_2 + 123
63 FrontBoardServices 0x00007fff365e0c45 -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 220
64 FrontBoardServices 0x00007fff365fc8dc __88-[FBSWorkspaceScenesClient sceneID:updateWithSettingsDiff:transitionContext:completion:]_block_invoke + 196
65 libdispatch.dylib 0x000000010610ed48 _dispatch_client_callout + 8
66 libdispatch.dylib 0x0000000106111cb9 _dispatch_block_invoke_direct + 300
67 FrontBoardServices 0x00007fff3662237e __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
68 FrontBoardServices 0x00007fff3662206c -[FBSSerialQueue _queue_performNextIfPossible] + 441
69 FrontBoardServices 0x00007fff3662257b -[FBSSerialQueue _performNextFromRunLoopSource] + 22
70 CoreFoundation 0x00007fff23bd4471 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
71 CoreFoundation 0x00007fff23bd439c __CFRunLoopDoSource0 + 76
72 CoreFoundation 0x00007fff23bd3b74 __CFRunLoopDoSources0 + 180
73 CoreFoundation 0x00007fff23bce87f __CFRunLoopRun + 1263
74 CoreFoundation 0x00007fff23bce066 CFRunLoopRunSpecific + 438
75 GraphicsServices 0x00007fff384c0bb0 GSEventRunModal + 65
76 UIKitCore 0x00007fff48092d4d UIApplicationMain + 1621
77 MyApplication 0x00000001041a68db main + 107
78 libdyld.dylib 0x00007fff5227ec25 start + 1
79 ??? 0x0000000000000002 0x0 + 2
)
libc++abi.dylib: terminating with uncaught exception of type NSException
我发现这个崩溃是由于 datePicker(或者可能是其中的 table)即 UIPickerTableView 而发生的。代码在 UIPickerTableView 的第 self.endUpdates() 行崩溃。请找到我创建的虚拟应用程序的代码:
class ViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
let datePicker = UIDatePicker()
datePicker.datePickerMode = .date
self.tableView.tableFooterView = datePicker
}
}
extension UITableView {
open override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
self.beginUpdates()
self.endUpdates()
}
}
如果有人能帮助我理解这次崩溃的根本原因,我会很高兴。
经过评论和一些测试...
- 崩溃发生在 iOS 13.3,而不是 iOS 13.4
- on iOS 13.4,
traitCollectionDidChange
in the extension 甚至没有被调用
- 在iOS 13.3,它被调用了,实际上被调用了10次(我的快速测试观察)
- 重复调用
beginUpdates()
endUpdates()
导致崩溃
- 这些调用可能(几乎可以肯定)不需要以
开头
关于beginUpdates()
endUpdates()
...
的一点澄清
它们告诉 table 视图处理/动画更改 table 而无需 重新加载单元格。一个常见的用法是展开/折叠单元格,使用 "callback" 闭包。
假设一个自定义单元格包含各种 UI 元素,包括一个 "Expand / Collapse" 按钮。 cellForRowAt
中的代码可能如下所示:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let c = tableView.dequeueReusableCell(withIdentifier: "sCell", for: indexPath) as! SimpleCell
c.myLabel.text = "\(indexPath)"
c.callback = {
c.myHeightConstraint.constant = c.myHeightConstraint.constant == 21 ? 60 : 21
tableView.beginUpdates()
tableView.endUpdates()
}
return c
}
当在单元格中点击按钮时,它会回调闭包,将我们的单元格 myHeightConstraint
在 21 和 60 之间切换。With 这些调用,我们看到行的高度动画。 没有 那些调用,行不会改变高度,直到其他东西告诉 table 视图重新计算/重新布局行。
请注意,Apple 的文档指出这些调用正在逐步淘汰/弃用,取而代之的是 performBatchUpdates()
:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let c = tableView.dequeueReusableCell(withIdentifier: "sCell", for: indexPath) as! SimpleCell
c.myLabel.text = "\(indexPath)"
c.callback = {
c.myHeightConstraint.constant = c.myHeightConstraint.constant == 21 ? 60 : 21
tableView.performBatchUpdates(nil, completion: nil)
}
return c
}
将完成同样的事情。
因此,由于这些调用没有做任何事情 - 除了 导致崩溃 - 听起来它们应该被删除。
我正在添加一个 UIDatePicker 作为 table 的页脚。我有另一个 UITableView 扩展,它实现了 traitCollectionDidChange 并且只执行 beginUpdates 和 endUpdates。我在更改方向时遇到以下崩溃。
*** Assertion failure in -[UIPickerTableView _Bug_Detected_In_Client_Of_UITableView_Invalid_Number_Of_Rows_In_Section:],
/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore_Sim/UIKit-3901.4.2/UITableView.m:2407
2020-05-12 13:35:28.729340+0530 MyApplication[41892:1575639] *** Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0.
The number of rows contained in an existing section after the update (0) must be equal to the number of
rows contained in that section before the update (10000), plus or minus the number of rows inserted or
deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into
or out of that section (0 moved in, 0 moved out).'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff23c7127e __exceptionPreprocess + 350
1 libobjc.A.dylib 0x00007fff513fbb20 objc_exception_throw + 48
2 CoreFoundation 0x00007fff23c70ff8 +[NSException raise:format:arguments:] + 88
3 Foundation 0x00007fff256e9b51 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 191
4 UIKitCore 0x00007fff4825d508 -[UITableView _Bug_Detected_In_Client_Of_UITableView_Invalid_Number_Of_Rows_In_Section:] + 193
5 UIKitCore 0x00007fff4825cdc1 -[UITableView _endCellAnimationsWithContext:] + 16657
6 UIKitCore 0x00007fff48276e0b -[UITableView endUpdatesWithContext:] + 112
7 MyApplication 0x0000000103d13ed1 -[UITableView(RIAdditions) traitCollectionDidChange:] + 97
8 UIKitCore 0x00007fff4854ccc4 -[UIView _traitCollectionDidChangeInternal:] + 977
9 UIKitCore 0x00007fff4854d5c4 -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 161
10 UIKitCore 0x00007fff4854d80a -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 743
11 UIKitCore 0x00007fff4854d80a -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 743
12 UIKitCore 0x00007fff4854d80a -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 743
13 UIKitCore 0x00007fff4854d80a -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 743
14 UIKitCore 0x00007fff4854d80a -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 743
15 UIKitCore 0x00007fff4854d7ae -[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 651
16 UIKitCore 0x00007fff4854d935 -[UIView _processDidChangeRecursivelyFromOldTraits:toCurrentTraits:forceNotification:] + 140
17 UIKitCore 0x00007fff485783d2 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2243
18 QuartzCore 0x00007fff2b131db1 -[CALayer layoutSublayers] + 255
19 QuartzCore 0x00007fff2b137fa3 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 517
20 UIKitCore 0x00007fff48563635 -[UIView(Hierarchy) layoutBelowIfNeeded] + 980
21 UIKitCore 0x00007fff47978038 -[UINavigationController _layoutViewController:] + 1465
22 UIKitCore 0x00007fff479710e9 -[UINavigationController _layoutTopViewControllerLookForNested:] + 589
23 UIKitCore 0x00007fff47966e9a __105-[UINavigationController _repositionPaletteWithNavigationBarHidden:duration:shouldUpdateNavigationItems:]_block_invoke + 718
24 UIKitCore 0x00007fff47966b9c -[UINavigationController _repositionPaletteWithNavigationBarHidden:duration:shouldUpdateNavigationItems:] + 308
25 UIKitCore 0x00007fff47970339 -[UINavigationController _updateBarsForCurrentInterfaceOrientationAndForceBarLayout:] + 174
26 UIKitCore 0x00007fff47980763 __84-[UINavigationController willTransitionToTraitCollection:withTransitionCoordinator:]_block_invoke + 639
27 UIKitCore 0x00007fff47a42124 -[_UIViewControllerTransitionCoordinator _applyBlocks:releaseBlocks:] + 294
28 UIKitCore 0x00007fff47a3e446 -[_UIViewControllerTransitionContext __runAlongsideAnimations] + 263
29 UIKitCore 0x00007fff4856bde6 +[UIView(UIViewAnimationWithBlocks) _setupAnimationWithDuration:delay:view:options:factory:animations:start:animationStateGenerator:completion:] + 528
30 UIKitCore 0x00007fff4856c395 +[UIView(UIViewAnimationWithBlocks) animateWithDuration:delay:options:animations:completion:] + 99
31 UIKitCore 0x00007fff47a5665a __58-[_UIWindowRotationAnimationController animateTransition:]_block_invoke_2 + 278
32 UIKitCore 0x00007fff4856ff44 +[UIView(Internal) _performBlockDelayingTriggeringResponderEvents:forScene:] + 174
33 UIKitCore 0x00007fff47a563e8 __58-[_UIWindowRotationAnimationController animateTransition:]_block_invoke + 164
34 UIKitCore 0x00007fff4856bde6 +[UIView(UIViewAnimationWithBlocks) _setupAnimationWithDuration:delay:view:options:factory:animations:start:animationStateGenerator:completion:] + 528
35 UIKitCore 0x00007fff4856c395 +[UIView(UIViewAnimationWithBlocks) animateWithDuration:delay:options:animations:completion:] + 99
36 UIKitCore 0x00007fff47a562c0 -[_UIWindowRotationAnimationController animateTransition:] + 491
37 UIKitCore 0x00007fff480d2e9d -[UIWindow _rotateToBounds:withAnimator:transitionContext:] + 525
38 UIKitCore 0x00007fff480d58e0 -[UIWindow _rotateWindowToOrientation:updateStatusBar:duration:skipCallbacks:] + 2331
39 UIKitCore 0x00007fff480d5ed3 -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] + 633
40 UIKitCore 0x00007fff480d4e27 -[UIWindow _setRotatableViewOrientation:updateStatusBar:duration:force:] + 119
41 UIKitCore 0x00007fff480d3ca4 __57-[UIWindow _updateToInterfaceOrientation:duration:force:]_block_invoke + 111
42 UIKitCore 0x00007fff480d3bcd -[UIWindow _updateToInterfaceOrientation:duration:force:] + 455
43 CoreFoundation 0x00007fff23b9b5bc __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
44 CoreFoundation 0x00007fff23b9aa35 _CFXRegistrationPost1 + 421
45 CoreFoundation 0x00007fff23b9a7a1 ___CFXNotificationPost_block_invoke + 193
46 CoreFoundation 0x00007fff23c988b3 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1811
47 CoreFoundation 0x00007fff23b9a0f6 _CFXNotificationPost + 950
48 Foundation 0x00007fff2574bbf7 -[NSNotificationCenter postNotificationName:object:userInfo:] + 59
49 UIKitCore 0x00007fff47cd5955 -[UIDevice setOrientation:animated:] + 224
50 UIKitCore 0x00007fff477c83f1 __134-[_UIWindowSceneDeviceOrientationSettingsDiffAction _updateDeviceOrientationWithSettingObserverContext:windowScene:transitionContext:]_block_invoke + 137
51 UIKitCore 0x00007fff47bd8c83 +[BSAnimationSettings(UIKit) tryAnimatingWithSettings:actions:completion:] + 865
52 UIKitCore 0x00007fff47cd2dff _UISceneSettingsDiffActionPerformChangesWithTransitionContext + 240
53 UIKitCore 0x00007fff477c8336 -[_UIWindowSceneDeviceOrientationSettingsDiffAction _updateDeviceOrientationWithSettingObserverContext:windowScene:transitionContext:] + 248
54 UIKitCore 0x00007fff477c8231 __163-[_UIWindowSceneDeviceOrientationSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:]_block_invoke + 112
55 UIKitCore 0x00007fff47cd2d02 _UISceneSettingsDiffActionPerformActionsWithDelayForTransitionContext + 84
56 UIKitCore 0x00007fff477c80c1 -[_UIWindowSceneDeviceOrientationSettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:] + 216
57 UIKitCore 0x00007fff476206e7 __64-[UIScene scene:didUpdateWithDiff:transitionContext:completion:]_block_invoke + 657
58 UIKitCore 0x00007fff4761f26c -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:] + 248
59 UIKitCore 0x00007fff47620411 -[UIScene scene:didUpdateWithDiff:transitionContext:completion:] + 210
60 UIKitCore 0x00007fff47bfac66 -[UIApplicationSceneClientAgent scene:handleEvent:withCompletion:] + 504
61 FrontBoardServices 0x00007fff365d6c07 -[FBSSceneImpl updater:didUpdateSettings:withDiff:transitionContext:completion:] + 565
62 FrontBoardServices 0x00007fff365fc99f __88-[FBSWorkspaceScenesClient sceneID:updateWithSettingsDiff:transitionContext:completion:]_block_invoke_2 + 123
63 FrontBoardServices 0x00007fff365e0c45 -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] + 220
64 FrontBoardServices 0x00007fff365fc8dc __88-[FBSWorkspaceScenesClient sceneID:updateWithSettingsDiff:transitionContext:completion:]_block_invoke + 196
65 libdispatch.dylib 0x000000010610ed48 _dispatch_client_callout + 8
66 libdispatch.dylib 0x0000000106111cb9 _dispatch_block_invoke_direct + 300
67 FrontBoardServices 0x00007fff3662237e __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
68 FrontBoardServices 0x00007fff3662206c -[FBSSerialQueue _queue_performNextIfPossible] + 441
69 FrontBoardServices 0x00007fff3662257b -[FBSSerialQueue _performNextFromRunLoopSource] + 22
70 CoreFoundation 0x00007fff23bd4471 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
71 CoreFoundation 0x00007fff23bd439c __CFRunLoopDoSource0 + 76
72 CoreFoundation 0x00007fff23bd3b74 __CFRunLoopDoSources0 + 180
73 CoreFoundation 0x00007fff23bce87f __CFRunLoopRun + 1263
74 CoreFoundation 0x00007fff23bce066 CFRunLoopRunSpecific + 438
75 GraphicsServices 0x00007fff384c0bb0 GSEventRunModal + 65
76 UIKitCore 0x00007fff48092d4d UIApplicationMain + 1621
77 MyApplication 0x00000001041a68db main + 107
78 libdyld.dylib 0x00007fff5227ec25 start + 1
79 ??? 0x0000000000000002 0x0 + 2
)
libc++abi.dylib: terminating with uncaught exception of type NSException
我发现这个崩溃是由于 datePicker(或者可能是其中的 table)即 UIPickerTableView 而发生的。代码在 UIPickerTableView 的第 self.endUpdates() 行崩溃。请找到我创建的虚拟应用程序的代码:
class ViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
let datePicker = UIDatePicker()
datePicker.datePickerMode = .date
self.tableView.tableFooterView = datePicker
}
}
extension UITableView {
open override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
self.beginUpdates()
self.endUpdates()
}
}
如果有人能帮助我理解这次崩溃的根本原因,我会很高兴。
经过评论和一些测试...
- 崩溃发生在 iOS 13.3,而不是 iOS 13.4
- on iOS 13.4,
traitCollectionDidChange
in the extension 甚至没有被调用 - 在iOS 13.3,它被调用了,实际上被调用了10次(我的快速测试观察)
- 重复调用
beginUpdates()
endUpdates()
导致崩溃 - 这些调用可能(几乎可以肯定)不需要以 开头
- 重复调用
关于beginUpdates()
endUpdates()
...
它们告诉 table 视图处理/动画更改 table 而无需 重新加载单元格。一个常见的用法是展开/折叠单元格,使用 "callback" 闭包。
假设一个自定义单元格包含各种 UI 元素,包括一个 "Expand / Collapse" 按钮。 cellForRowAt
中的代码可能如下所示:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let c = tableView.dequeueReusableCell(withIdentifier: "sCell", for: indexPath) as! SimpleCell
c.myLabel.text = "\(indexPath)"
c.callback = {
c.myHeightConstraint.constant = c.myHeightConstraint.constant == 21 ? 60 : 21
tableView.beginUpdates()
tableView.endUpdates()
}
return c
}
当在单元格中点击按钮时,它会回调闭包,将我们的单元格 myHeightConstraint
在 21 和 60 之间切换。With 这些调用,我们看到行的高度动画。 没有 那些调用,行不会改变高度,直到其他东西告诉 table 视图重新计算/重新布局行。
请注意,Apple 的文档指出这些调用正在逐步淘汰/弃用,取而代之的是 performBatchUpdates()
:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let c = tableView.dequeueReusableCell(withIdentifier: "sCell", for: indexPath) as! SimpleCell
c.myLabel.text = "\(indexPath)"
c.callback = {
c.myHeightConstraint.constant = c.myHeightConstraint.constant == 21 ? 60 : 21
tableView.performBatchUpdates(nil, completion: nil)
}
return c
}
将完成同样的事情。
因此,由于这些调用没有做任何事情 - 除了 导致崩溃 - 听起来它们应该被删除。