【问题标题】:EditButton() in SwiftUI inside a ScrollView / LazyVGridScrollView / LazyVGrid 中的 SwiftUI 中的 EditButton()
【发布时间】:2021-04-21 16:21:31
【问题描述】:

SwiftUI(Xcode 12.5 beta 3)中的 EditButton() 似乎存在各种问题。

在我的代码中,一切正常,直到我将 List 替换为 ScrollView 并添加了 LazyVGrid。现在,当用户点击 EditButton 时,EditMode 不会被激活。

任何解决方法的想法?拥有 2 列是 UI 的要求,虽然我可以使用列表,但我更喜欢 ScrollView 的外观。我已经尝试了很多东西......将 ForEach 放在一个部分中并将 EditButton 放在标题中,用手动按钮替换它......不幸的是它们似乎都不起作用:-(

非常感谢任何想法或其他人为解决此问题所做的任何事情。

struct Home: View {
    @Environment(\.managedObjectContext) private var viewContext
    @FetchRequest(entity: Cars.entity(), sortDescriptors: []) var cars: FetchedResults<Cars>
    
    private var columns: [GridItem] = [
            GridItem(.flexible()),
            GridItem(.flexible())
        ]

    var body: some View {
  
        NavigationView {
            ScrollView {

                if cars.count > 0 {
                    LazyVGrid(
                        columns: columns) {
                
                ForEach(cars) { n in
                    Text("hello")
                }
                .onDelete(perform: deleteCars)
                    }    
                }
                
                else {
                    Text("You have no cars.")
                }   
            } 
            .navigationBarItems(leading: EditButton())       
        }   
    }
    
    func deleteCars(at offsets: IndexSet) {
        for offset in offsets {
            let cars = cars[offset]
            viewContext.delete(cars)
        }
        try? viewContext.save()
    }
    
}

尝试 1

看完下面Asperi的cmets后,我在ScrollView中添加了以下(下)手动创建按钮,触发EditMode和移除项目。现在我在deleteCars 行收到一个新错误:“Initializer 'init(_:)' 要求 'FetchedResults.Element' (aka 'Cars') 符合 'Sequence'”。

似乎我真的很接近,但仍在挣扎 - 谁能帮助我完成最后的部分?非常感谢!

@State var isEditing = false

...

ScrollView {

                if cars.count > 0 {
                    LazyVGrid(
                        columns: columns) {
                        ForEach(cars) { n in
                    Text("hello")
                    Button(action : {
                        deleteCars(at: IndexSet(n))
                        print("item deleted")
                    })
                    
                    {Text("\(isEditing ? "Delete me" : "not editing")")}
                }
                .onDelete(perform: deleteCars)
                .environment(\.editMode, .constant(self.isEditing ? EditMode.active : EditMode.inactive)).animation(Animation.spring())
                    }
                }
                else {
                    Text("You have no cars.")
                }
                Button(action: {
                                    self.isEditing.toggle()
                                }) {
                                    Text(isEditing ? "Done" : "Edit")
                                        .frame(width: 80, height: 40)
                                }
            
            }

【问题讨论】:

  • EditMode 已激活,只是 ScrollView 没有 List 对 EditMode 的内置功能。如果你想要一些你需要手动处理它。

标签: swiftui swiftui-scrollview lazyvgrid


【解决方案1】:

TLDR:手动创建一个 EditButton 并将其直接添加到 ForEach 循环中。确保 ForEach 数组具有指定的索引。

好的,随着上述尝试 1 的进展,终于找到了答案……通过将 .indices 添加到 ForEach 循环中的数组来工作。全文如下:

struct Home: View {
    @Environment(\.managedObjectContext) private var viewContext
    @FetchRequest(entity: Cars.entity(), sortDescriptors: []) var cars: FetchedResults<Cars>

    @State var isEditing = false
    
    private var columns: [GridItem] = [
            GridItem(.flexible()),
            GridItem(.flexible())
        ]

    var body: some View {
  
        NavigationView {
            VStack{   
            ScrollView {

                if cars.count > 0 {
                    LazyVGrid(
                        columns: columns) {
                    ForEach(cars.indices, id: \.self) { n in
                    Text("hello")
                    Button(action : {
                        deleteCars(at: [n])
                        print("item deleted")
                    })
                    
                    {Text("\(isEditing ? "Delete me" : "not editing")")}
                        }
                }
                .environment(\.editMode, .constant(self.isEditing ? EditMode.active : EditMode.inactive)).animation(Animation.spring())
                    }
                }
                else {
                    Text("You have no cars.")
                }        
            }
            .navigationBarItems(leading: Button(action: {
                self.isEditing.toggle()
            }) {
                Text(isEditing ? "Done" : "Edit")
                    .frame(width: 80, height: 40)
            }
            ) 
        }   
    }
    
    func deleteCars(at offsets: IndexSet) {
        for offset in offsets {
            let cars = cars[offset]
            viewContext.delete(cars)
        }
        try? viewContext.save()
    }
    
}

我相信有很多方法可以优化这一点(代码和问题/答案的编写方式,所以请随时提出建议。

【讨论】:

    猜你喜欢
    • 2021-02-01
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    • 2019-12-12
    • 1970-01-01
    • 2022-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多