Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 可绑定属性更改时运行方法调用的SwiftUI_Ios_Swift_Swiftui - Fatal编程技术网

Ios 可绑定属性更改时运行方法调用的SwiftUI

Ios 可绑定属性更改时运行方法调用的SwiftUI,ios,swift,swiftui,Ios,Swift,Swiftui,我正在努力理解如何在可绑定对象发生变化时运行方法。以下是我目前掌握的代码: 然而,由于某种原因,fetchFoods方法从未因searchText的更改而被调用,我似乎不明白为什么。@Harish@Asperi各位,你们在这里搞混了。@Harish的方法没有被调用有一个特定的原因。让我们创建一个简单的示例: struct ContentView: View { @State private var text = "" { didSet { pri

我正在努力理解如何在可绑定对象发生变化时运行方法。以下是我目前掌握的代码:


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

@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()
    }
}
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()
    }
}
如果您复制粘贴并运行这个最小可行的示例,您将看到字符串“Triggered!”永远不会被打印出来。这是因为通过$binding更改的不是
文本
属性,而是通过
$
符号访问的绑定包装值。它们是两个完全不同的东西。理解这一点非常重要

那么,@Asperi的例子为什么有效呢?(我稍微简化了它,以创建另一个最低可行的示例):

这一次,如果您复制粘贴此代码,您将看到“已触发!”将被打印。这是很好的,因为点击按钮,您正在完全改变
self.isOn
。这次您没有使用任何
$
符号来访问绑定包装的值

上面的例子似乎使用相同的方法,但实际上它们确实不同。再次强调,理解这种差异非常重要。那么,您如何获得您想要的(即“在可绑定对象发生变化时运行方法”)?您必须依赖于
ViewModel
@发布的
属性包装:

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 properties的客户端(通过$projection) 在值更改时接收更新