【发布时间】:2020-01-08 05:57:39
【问题描述】:
所以我一直在尝试使用swiftUI 制作一个组件,它允许您在部分之间移动List 中的项目。
我准备了一个包含两个部分的示例:“第一个列表”和“第二个列表”。每当您点击一个项目时,它会交换部分。截图如下:
当我点击“第一个列表:1”时,它会正确移动到第二部分:
但是,由于我在部分中命名元素的方式,它的名称现在应该更改为“第二列表:1”(请参见下面的代码)。所以这很奇怪。但它变得陌生:
当我现在在第二部分点击“第一个列表:1”时,会发生这种情况:
它没有正确交换回来。它只是被重复了,但这次重复的名称实际上是正确的。
考虑到下面的代码,我不明白这是怎么可能的。似乎swiftUI 以某种方式重用了该项目,即使它重新呈现了视图?它似乎也重用了.onTapGesture 闭包,因为本应将项目放回第一部分的方法实际上从未被调用过。
知道这里发生了什么吗?以下是该问题的完整示例:
import SwiftUI
import Combine
struct TestView: View {
@ObservedObject var viewModel: ViewModel
class ViewModel: ObservableObject {
let objectWillChange = PassthroughSubject<ViewModel,Never>()
public enum List {
case first
case second
}
public var first: [Int] = []
public var second: [Int] = []
public func swap(elementWithIdentifier identifier: Int, from list: List) {
switch list {
case .first:
self.first.removeAll(where: {$0 == identifier})
self.second.append(identifier)
case .second:
print("Called")
self.second.removeAll(where: {$0 == identifier})
self.first.append(identifier)
}
self.objectWillChange.send(self)
}
init(first: [Int]) {
self.first = first
}
}
var body: some View {
NavigationView {
List {
Section(header: Text("First List")) {
ForEach(self.viewModel.first, id: \.self) { id in
Text("First List: \(id)")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onTapGesture {
self.viewModel.swap(elementWithIdentifier: id, from: .first)
}
}
}
Section(header: Text("First List")) {
ForEach(self.viewModel.second, id: \.self) { id in
Text("Second List: \(id)")
.onTapGesture {
self.viewModel.swap(elementWithIdentifier: id, from: .second)
}
}
}
}
.listStyle(GroupedListStyle())
.navigationBarTitle(Text("Testing"))
}.environment(\.editMode, .constant(EditMode.active))
}
}
struct TestView_Preview: PreviewProvider {
static var previews: some View {
TestView(viewModel: TestView.ViewModel(first: [1, 2, 3, 4, 5]))
}
}
【问题讨论】:
-
您的
var first和var second需要存在于外部模型对象中。TestView结构会在它所依赖的状态发生变化时由 SwiftUI 重新创建,因此您的数据会不断重新创建。要进行测试,请将您的数组作为全局变量移出,它应该可以按预期工作。 -
它们在外部模型对象中。它们是类
ViewModel的属性,充当ObservedObject。还是我弄错了? -
我知道这是一个较旧的线程,但我很想看看你是否能够让它工作
-
不,抱歉。很遗憾,我还没有找到解决方案