当可绑定属性更改时,SwiftUI运行方法调用

时间:2019-11-03 12:43:38

标签: ios swift swiftui

我在努力理解当可绑定对象更改时如何运行方法。这是我到目前为止的代码: enter image description here

但是,由于某种原因,由于searchText的更改,fetchFoods方法从未被调用,而且我似乎不明白为什么。

1 个答案:

答案 0 :(得分:0)

@Harish @Asperi,您在这里让人感到困惑。导致@Harish方法不被调用的特定原因。让我们创建一个简单的示例:

struct ContentView: View {
    @State private var text = "" {
        didSet {
            print("Triggered!")
        }
    }

    var body: some View {
        VStack {
            TextField("Type something...", text: $text)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

如果您复制粘贴并运行此最小可行示例,则会看到字符串“ Triggered!”。永远不会被打印。这是因为您通过$绑定进行更改的不是text属性,而是通过$符号访问的绑定包装值 。它们是完全不同的两件事。了解这一点非常重要。

那么,为什么@Asperi的示例起作用? (我稍微简化了它,以创建另一个最小可行的示例):

struct ContentView: View {
    @State private var isOn = false {
        didSet {
            print("Triggered!")
        }
    }
    var body: some View {
        Button(
            action: { self.isOn.toggle() },
            label: { Text(self.isOn ? "Hide" : "Show") }
        )
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

这次,如果您复制粘贴此代码,则会看到“已触发!”将被打印。这很好,因为轻按按钮即可更改self.isOn。这次您没有使用任何$符号来访问绑定包装的值。

上面的示例似乎使用相同的方法,但实际上它们确实不同。同样,了解这种差异非常重要。那么,如何获得所需的内容(即“在Bindable对象更改时运行方法”)?您必须依靠ViewModel@Published属性包装器:

class ViewModel: ObservableObject {
    @Published var text = "" {
        didSet {
            print("Triggered!")
        }
    }
}

struct ContentView: View {
    @ObservedObject var viewModel = ViewModel()

    var body: some View {
        VStack {
            TextField("Type something...", text: $viewModel.text)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

正是出于此目的:

  

Combine的Published属性包装器在精神上类似于其他属性包装器,允许   客户订阅@Published属性(通过$投影)   当值更改时接收更新

来自https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md