如何在不使用swiftUI附带的幻灯片删除的情况下创建自定义删除按钮我没有使用列表,只是使用foreach循环
Posted
技术标签:
【中文标题】如何在不使用swiftUI附带的幻灯片删除的情况下创建自定义删除按钮我没有使用列表,只是使用foreach循环【英文标题】:How to create a custom delete button without using the slide to delete that comes with swiftUI I am not using list, just using a foreach loop 【发布时间】:2020-09-10 06:47:07 【问题描述】:由于 onDelete 和 onMove 是 List/form 的功能,当我有没有它们的自定义界面时,我无法使用它们。我在 ForEach 中使用了 VStack。我对 swiftUI 很陌生,不确定如何为 onDelete 和 onMove 实现自定义代码。
这是我的代码:
struct Trying: View
@State private var numbers = [0,1,2,3,4,5,6,7,8,9]
var body: some View
NavigationView
VStack (spacing: 10)
ForEach(numbers, id: \.self) number in
VStack
Text("\(number)")
.frame(width: 50, height: 50)
.background(Color.red)
.onDelete(perform: removeRows)
.navigationTitle("Trying")
.navigationBarItems(trailing: EditButton())
func removeRows(at offsets: IndexSet)
numbers.remove(atOffsets: offsets)
现在的工作方式:
【问题讨论】:
【参考方案1】:这是实现自定义删除的可能方法的简单演示(当然,由于拖放,移动会更复杂,但想法是相同的)。使用 Xcode 12 / ios 14 测试。
struct DemoCustomDelete: View
@State private var numbers = [0,1,2,3,4,5,6,7,8,9]
var body: some View
NavigationView
VStack (spacing: 10)
ForEach(numbers, id: \.self) number in
VStack
Text("\(number)")
.frame(width: 50, height: 50)
.background(Color.red)
.overlay(
DeleteButton(number: number, numbers: $numbers, onDelete: removeRows)
, alignment: .topTrailing)
.onDelete(perform: removeRows)
.navigationTitle("Trying")
.navigationBarItems(trailing: EditButton())
func removeRows(at offsets: IndexSet)
withAnimation
numbers.remove(atOffsets: offsets)
struct DeleteButton: View
@Environment(\.editMode) var editMode
let number: Int
@Binding var numbers: [Int]
let onDelete: (IndexSet) -> ()
var body: some View
VStack
if self.editMode?.wrappedValue == .active
Button(action:
if let index = numbers.firstIndex(of: number)
self.onDelete(IndexSet(integer: index))
)
Image(systemName: "minus.circle")
.offset(x: 10, y: -10)
【讨论】:
-查看您的解决方案,我想知道这是否适用于 CoreData?我有一个lazyHGrid,它显示了FetchRequest 的结果。我无法弄清楚如何获得有效的删除功能。在我切换到lazyHGrid之前,我使用的是一个简单的列表,我可以通过 - private func deleteEvent(offsets: IndexSet) withAnimation offsets.map events[$0] .forEach(moc.delete) do try moc. save() catch let nsError = error as NSError fatalError("未解决的错误 (nsError), (nsError.userInfo)") 【参考方案2】:根据@Asperi 的回答,我只是将其概括为接受任何Equatable
序列。
struct DeleteButton<T>: View where T: Equatable
@Environment(\.editMode) var editMode
let number: T
@Binding var numbers: [T]
let onDelete: (IndexSet) -> ()
var body: some View
VStack
if self.editMode?.wrappedValue == .active
Button(action:
if let index = numbers.firstIndex(of: number)
self.onDelete(IndexSet(integer: index))
)
Image(systemName: "minus.circle")
.offset(x: 10, y: -10)
【讨论】:
【参考方案3】:我最近需要删除一行,但我无法使用 LIST。相反,我有一个滚动视图......但我能够实现编辑以模拟相同的 onDelete 行为,就好像它是一个列表一样。最初我无法让我的代码工作。直到我仔细检查了我的实现并进行了实验,我才偶然发现我的工作原理。我正在为 iPad 编写代码,以便我的 NavigationView 使用,
.navigationViewStyle(StackNavigationViewStyle())
一旦我将它添加到结构的 NavigationView 中,当您单击 EditButton 时,它会将 editMode?.wrappedValue 激活为 .active / .inactive
下面是我对上面代码示例的实现...
struct Trying: View
@State var num: Int = 0
@Environment(\.editMode) var editMode
@State private var numbers = [0,1,2,3,4,5,6,7,8,9]
var body: some View
NavigationView
VStack
ForEach(numbers, id: \.self) number in
HStack
if editMode?.wrappedValue == .active
Button(action: num = number
removeRows(numbr: num)
, label:
Image(systemName: "minus.circle.fill")
.foregroundColor(.red)
)
// END IF editMode?wrappedValue == .active
Text("\(number)")
.frame(width: 50, height: 50)
.background(Color.red)
// .onDelete(perform: removeRows)
.navigationTitle("Trying")
.navigationBarItems(trailing: EditButton())
// FOR SOME REASON THIS ALLOWS THE EditButton() to activate editMode without a LIST being present.
.navigationViewStyle(StackNavigationViewStyle())
func removeRows(numbr: Int)
print("removing \(numbr)")
看起来像:
【讨论】:
以上是关于如何在不使用swiftUI附带的幻灯片删除的情况下创建自定义删除按钮我没有使用列表,只是使用foreach循环的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI 如何在不使用 List 的情况下从 @ObservedObject ViewModel 获取 Firebase 数据
如何在不继承 SwiftUI 中其他已定义视图的情况下制作正文,苹果最初是如何做到的?
在不影响外框的情况下使用 SwiftUI GeometryReader?