swift 我如何在两个视图上使用相同的已发布数组,当我更改第一个视图中任何元素的索引号时,另一个视图没有?

chhqkbe1  于 2023-05-05  发布在  Swift
关注(0)|答案(1)|浏览(88)

我不确定这个问题是否足够清楚,但这是我的问题:
我有一个内容视图,其中有两个视图和一个@StateObject。我将这个变量作为@ObservedObject传递给第一个和第二个视图。我必须创建一个可观察的对象,因为当我在第二视图中单击一个项目时;在第一个视图上应该突出显示相同的项目。所以他们应该有联系。
当我在第二个视图中通过拖放功能更新元素的索引号时,我不希望它在第一个视图中被更新。
这是我的第一个问题,谢谢你的帮助

我知道它们共享相同的可观察对象,我知道为什么它不起作用;但我找不到解决办法:

struct ContentView: View {
    @StateObject var myArray = MyArray()

    var body: some View {
        HStack {
            FirstView(myArray: myArray)
            SecondView(myArray: myArray)
        }
    }
}

struct FirstView: View {
    @ObservedObject var myArray: MyArray

    var body: some View {
        VStack {
            Text("First View")
            ForEach(myArray.items, id: \.id) { item in
                Text(item.name)
                    .onDrag {
                        let index = myArray.items.firstIndex(where: { $0.id == item.id })!
                        return NSItemProvider(object: "\(index)" as NSString)
                    }
                    .onDrop(of: [.text], delegate: MyDropDelegate(myArray: myArray, currentItem: item))
            }

        }
    }
}

struct SecondView: View {
    @ObservedObject var myArray: MyArray

    var body: some View {
        VStack {
            Text("Second View")
            ForEach(myArray.items, id: \.id) { item in
                Text(item.name)
                    .onDrag {
                        let index = myArray.items.firstIndex(where: { $0.id == item.id })!
                        return NSItemProvider(object: "\(index)" as NSString)
                    }
                    .onDrop(of: [.text], delegate: MyDropDelegate(myArray: myArray, currentItem: item))
            }
        }
    }
}

class MyArray: ObservableObject {
    @Published var items = [MyItem(name: "Item 1"), MyItem(name: "Item 2"), MyItem(name: "Item 3")]
}
yqkkidmi

yqkkidmi1#

这实际上比预期的要棘手。问题是为选择的两个视图/数组保留一个真实来源,但在排序顺序上有所区别。
基本上我看到两种方式:
1.有一个项目数组,其中每个项目在每个视图中跟踪其位置(2个位置变量)
1.有两个相同元素的数组(这意味着你必须在两个数组中添加/删除)
我采用了方法2,并使用了新的List初始化器editActions: .move,它自动处理项的移动。选择是全局的,并传递到两个列表视图。

struct ContentView: View {
    
    @StateObject var myArray = MyArray()
    @State private var selection: MyItem.ID? = nil // global selection

    var body: some View {
        HStack {
            FirstView(myArray: myArray, selection: $selection)
            SecondView(myArray: myArray, selection: $selection)
        }
    }
}

struct FirstView: View {
    
    @ObservedObject var myArray: MyArray
    @Binding var selection: MyItem.ID?

    var body: some View {
        VStack {
            Text("First View")
            List ($myArray.items1, editActions: .move, selection: $selection) { $item in
                Text(item.name)
            }
            .listStyle(.plain)
        }
    }
}

struct SecondView: View {
    
    @ObservedObject var myArray: MyArray
    @Binding var selection: MyItem.ID?
    
    var body: some View {
        VStack {
            Text("Second View")
            List ($myArray.items2, editActions: .move, selection: $selection) { $item in
                Text(item.name)
            }
            .listStyle(.plain)
        }
    }
}

struct MyItem: Identifiable, Hashable {
    let id = UUID()
    var name: String
}

class MyArray: ObservableObject {
    
    init() { // create two arrays with the same content
        let items = [
            MyItem(name: "Item 1"),
            MyItem(name: "Item 2"),
            MyItem(name: "Item 3"),
            MyItem(name: "Item 4"),
            MyItem(name: "Item 5"),
        ]
        self.items1 = items
        self.items2 = items
    }
    
    @Published var items1: [MyItem]
    @Published var items2: [MyItem]

}

相关问题