[英]Attempt to delete item containing first responder that refused to resign
我试图根据showElements
值有条件地显示一个List
。 此List
包含一个ForEach
以显示names
数组的所有元素和一个TextField
以允许用户添加新名称。 将showElements
的值更改为 false 应删除names
数组和空name
字符串的所有元素。 上面的代码适用于 iOS 15 和 Xcode 13 但如果我使用 Xcode 14 运行相同的项目,则应用程序崩溃。 重现崩溃的步骤是:
Toggle
TextField
字段Toggle
(这里发生崩溃)这里的代码:
struct ContentView: View {
@State private var names: [String] = []
@State private var name: String = ""
@State private var showElements: Bool = false
var body: some View {
Form {
Section {
Toggle(isOn: $showElements) {
Text("ShowElements")
}
.onChange(of: showElements) { newValue in
if newValue == false {
name = ""
names = []
}
}
if showElements {
List {
ForEach(names, id: \.self) { name in
Text(name)
}
HStack {
TextField("name", text: $name)
Button {
names.append(name)
name = ""
} label: {
Text("Add")
}
}
}
}
}
}
}
}
这里是控制台日志:
2022-09-08 23:03:26.516945+0200 test[28915:875267] *** Assertion failure in -[SwiftUI.UpdateCoalescingCollectionView _resignOrRebaseFirstResponderViewWithUpdateItems:indexPathMapping:], UICollectionView.m:11437
2022-09-08 23:03:26.524664+0200 test[28915:875267] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Attempt to delete item containing first responder that refused to resign.
First responder that was asked to resign (returned YES from -resignFirstResponder): <UITextField: 0x7fa25b08aa00; frame = (0 0; 274.333 22); opaque = NO; autoresize = W+H; gestureRecognizers = <NSArray: 0x600002271c80>; placeholder = name; borderStyle = None; background = <_UITextFieldNoBackgroundProvider: 0x600002ec7c10: textfield=<UITextField 0x7fa25b08aa00>>; layer = <CALayer: 0x600002c7f540>> inside containing view: <SwiftUI.ListCollectionViewCell: 0x7fa25b054c00; baseClass = UICollectionViewListCell; frame = (20 79; 353 44); clipsToBounds = YES; layer = <CALayer: 0x600002c61400>> at index path: <NSIndexPath: 0xde7e4e75a67d6979> {length = 2, path = 0 - 1}
Current first responder: <_TtGC7SwiftUI15CellHostingViewGVS_15ModifiedContentVS_14_ViewList_ViewVS_26CollectionViewCellModifier__: 0x7fa25b012400; frame = (0 0; 353 44); autoresize = W+H; gestureRecognizers = <NSArray: 0x6000022750e0>; layer = <CALayer: 0x600002c616a0>> inside containing view: <SwiftUI.ListCollectionViewCell: 0x7fa25b054c00; baseClass = UICollectionViewListCell; frame = (20 79; 353 44); clipsToBounds = YES; layer = <CALayer: 0x600002c61400>> at index path: <NSIndexPath: 0xde7e4e75a67d6979> {length = 2, path = 0 - 1}'
*** First throw call stack:
(
0 CoreFoundation 0x00007ff800427378 __exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007ff80004dbaf objc_exception_throw + 48
2 Foundation 0x00007ff800b876ac _userInfoForFileAndLine + 0
3 UIKitCore 0x000000010b195c2f -[UICollectionView _resignOrRebaseFirstResponderViewWithUpdateItems:indexPathMapping:] + 1340
4 UIKitCore 0x000000010b1939bc -[UICollectionView _updateWithItems:tentativelyForReordering:propertyAnimator:collectionViewAnimator:] + 226
5 UIKitCore 0x000000010b18a71b -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:collectionViewAnimator:] + 14344
6 UIKitCore 0x000000010b19814c -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:animator:animationHandler:] + 577
7 UIKitCore 0x000000010b197e7d -[UICollectionView performBatchUpdates:completion:] + 34
8 SwiftUI 0x000000010ec02c4f block_destroy_helper + 25991
9 SwiftUI 0x000000010ec03453 block_destroy_helper + 28043
10 SwiftUI 0x000000010f23985e __swift_memcpy56_4 + 159666
11 SwiftUI 0x000000010eda93be block_destroy_helper.23 + 66721
12 SwiftUI 0x000000010eda93d4 block_destroy_helper.23 + 66743
13 UIKitCore 0x000000010c277eff +[UIView(Animation) performWithoutAnimation:] + 84
14 SwiftUI 0x000000010f23aaa0 __swift_memcpy56_4 + 164340
15 SwiftUI 0x000000010f1298f8 objectdestroy.136Tm + 41411
16 SwiftUI 0x000000010ee4a86f block_destroy_helper + 35480
17 SwiftUI 0x000000010ee4a1d0 block_destroy_helper + 33785
18 SwiftUI 0x000000010eb35a78 __swift_assign_boxed_opaque_existential_1 + 70088
19 SwiftUI 0x000000010eb359db __swift_assign_boxed_opaque_existential_1 + 69931
20 SwiftUI 0x000000010eb35ad1 __swift_assign_boxed_opaque_existential_1 + 70177
21 CoreFoundation 0x00007ff800385fe5 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
22 CoreFoundation 0x00007ff800380952 __CFRunLoopDoObservers + 515
23 CoreFoundation 0x00007ff800380e9d __CFRunLoopRun + 1161
24 CoreFoundation 0x00007ff800380637 CFRunLoopRunSpecific + 560
25 GraphicsServices 0x00007ff809c0f28a GSEventRunModal + 139
26 UIKitCore 0x000000010bc5d425 -[UIApplication _run] + 994
27 UIKitCore 0x000000010bc62301 UIApplicationMain + 123
28 SwiftUI 0x000000010f6dbfa3 __swift_memcpy53_8 + 95801
29 SwiftUI 0x000000010f6dbe50 __swift_memcpy53_8 + 95462
30 SwiftUI 0x000000010edfbafc __swift_memcpy195_8 + 12192
31 test 0x000000010a63123e $s4test0A3AppV5$mainyyFZ + 30
32 test 0x000000010a6312c9 main + 9
33 dyld 0x000000010a87c2bf start_sim + 10
34 ??? 0x000000011700252e 0x0 + 4680852782
)
libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Attempt to delete item containing first responder that refused to resign.
First responder that was asked to resign (returned YES from -resignFirstResponder): <UITextField: 0x7fa25b08aa00; frame = (0 0; 274.333 22); opaque = NO; autoresize = W+H; gestureRecognizers = <NSArray: 0x600002271c80>; placeholder = name; borderStyle = None; background = <_UITextFieldNoBackgroundProvider: 0x600002ec7c10: textfield=<UITextField 0x7fa25b08aa00>>; layer = <CALayer: 0x600002c7f540>> inside containing view: <SwiftUI.ListCollectionViewCell: 0x7fa25b054c00; baseClass = UICollectionViewListCell; frame = (20 79; 353 44); clipsToBounds = YES; layer = <CALayer: 0x600002c61400>> at index path: <NSIndexPath: 0xde7e4e75a67d6979> {length = 2, path = 0 - 1}
Current first responder: <_TtGC7SwiftUI15CellHostingViewGVS_15ModifiedContentVS_14_ViewList_ViewVS_26CollectionViewCellModifier__: 0x7fa25b012400; frame = (0 0; 353 44); autoresize = W+H; gestureRecognizers = <NSArray: 0x6000022750e0>; layer = <CALayer: 0x600002c616a0>> inside containing view: <SwiftUI.ListCollectionViewCell: 0x7fa25b054c00; baseClass = UICollectionViewListCell; frame = (20 79; 353 44); clipsToBounds = YES; layer = <CALayer: 0x600002c61400>> at index path: <NSIndexPath: 0xde7e4e75a67d6979> {length = 2, path = 0 - 1}'
terminating with uncaught exception of type NSException
CoreSimulator 857.7 - Device: iPhone 14 Pro (157A86B8-D8A5-4E19-A9B1-B6D9971F2A97) - Runtime: iOS 16.0 (20A360) - DeviceType: iPhone 14 Pro
(lldb)
我怎么解决这个问题?
仅当您尝试更改仍保持焦点的 TextField 时,才会发生这种情况。 如果您添加新元素并且不单击/关注文本字段并更改切换 state,您将看到您的代码不会崩溃。
要解决此问题,请将@FocusState添加到 TextField
@FocusState private var textFieldIsFocused: Bool
TextField("name", text: $name)
.focused($textFieldIsFocused)
并在更改 Toggle state 之前失去焦点。 为了实现这一点,我向 Toggle 添加了一个自定义绑定,这样我们就可以在更改 state 之前释放 TextField 焦点。
Toggle(
isOn:
.init(
get: { showElements },
set: {
textFieldIsFocused = false
showElements = $0
}
)
) {
Text("ShowElements")
}
.onChange(of: showElements) { newValue in
if newValue == false {
name = ""
names = []
}
}
import SwiftUI
struct ContentView: View {
@State private var names: [String] = []
@State private var name: String = ""
@State private var showElements: Bool = false
@FocusState private var textFieldIsFocused: Bool
var body: some View {
Form {
Section {
Toggle(
isOn:
.init(
get: { showElements },
set: {
textFieldIsFocused = false
showElements = $0
}
)
) {
Text("ShowElements")
}
.onChange(of: showElements) { newValue in
if newValue == false {
name = ""
names = []
}
}
if showElements {
List {
ForEach(names, id: \.self) { name in
Text(name)
}
HStack {
TextField("name", text: $name)
.focused($textFieldIsFocused)
Button {
names.append(name)
name = ""
} label: {
Text("Add")
}
}
}
}
}
}
}
}
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
快乐编码,
科尔玛·卡夫兰(:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.