iOS 14.3 中数组为空时崩溃

Posted

技术标签:

【中文标题】iOS 14.3 中数组为空时崩溃【英文标题】:Crash when array is empty in iOS 14.3 【发布时间】:2021-01-10 13:37:03 【问题描述】:

我试图在数组为空时显示一些占位符数据。这在 ios 13.7 中有效,但在 iOS 14.3 中发生了一些变化,所以当最后一个项目被删除时,你会遇到这个崩溃:

致命错误:索引超出范围:文件 Swift/ContiguousArrayBuffer.swift,第 444 行

如果我注释掉 testStore.data.isEmpty 并返回 Form 我不会崩溃。

如何在 iOS 14.3 中数组为空时显示占位符?

struct Test: Identifiable 
    var text: String
    var id: String  text 


extension Test 
    final class Store: ObservableObject 
        @Published var data = [Test(text: "Hi"), Test(text: "Bye")]
    


struct TestList: View 
    
    @EnvironmentObject var testStore: Test.Store
    
    var body: some View 
        Group 
            if testStore.data.isEmpty 
                Text("Empty")
             else 
                Form 
                    ForEach(testStore.data.indices, id: \.self)  index in
                        TestRow(test: $testStore.data[index], deleteHandler:  testStore.data.remove(at: index) )
                    
                
            
        
    


struct TestRow: View 
    
    @Binding var test: Test
    let deleteHandler: (() -> ())
    
    var body: some View 
        HStack 
            Text(test.text)
                .font(.headline)
            Spacer()
            Button(action: deleteHandler, label: Image(systemName: "trash"))
        
    

【问题讨论】:

这能回答你的问题吗? SwiftUI ForEach index out of range error when removing row @Andrew 不幸的是,没有,我搜索了所有 SO 无济于事。欢迎您自己尝试代码。 检查一下,类似:***.com/a/59007863/14733292 删除绑定,而不是这个传递 testStore 对象和索引 这能回答你的问题吗? Deleting list elements from SwiftUI's List 【参考方案1】:

您可以使用建议的扩展here:

struct Safe<T: RandomAccessCollection & MutableCollection, C: View>: View 
    typealias BoundElement = Binding<T.Element>
    private let binding: BoundElement
    private let content: (BoundElement) -> C

    init(_ binding: Binding<T>, index: T.Index, @ViewBuilder content: @escaping (BoundElement) -> C) 
        self.content = content
        self.binding = .init(get:  binding.wrappedValue[index] ,
                             set:  binding.wrappedValue[index] = $0 )
    

    var body: some View 
        content(binding)
    

然后,如果您还想保留ForEach 而不是List,您可以这样做:

struct TestList: View 
    @EnvironmentObject var testStore: Test.Store

    var body: some View 
        Group 
            if testStore.data.isEmpty 
                Text("Empty")
             else 
                Form 
                    ForEach(testStore.data.indices, id: \.self)  index in
                        Safe($testStore.data, index: index)  binding in
                            TestRow(test: binding, deleteHandler:  testStore.data.remove(at: index) )
                        
                    
                
            
        
    

【讨论】:

以上是关于iOS 14.3 中数组为空时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

MongoDb 仅当数组不为空时才在数组中添加字段

Laravel:当数组为空时数组循环的集合

在聚合管道中过滤数组为空时保留主文档

当过滤器为空时,它返回空数组

vue中当数据为空时的处理

mybatis 如何判断数组是不是为空,空时不循环数组