Swift有一个非常类似于C#的属性声明语法:
var foo: Int {
get { return getFoo() }
set { setFoo(newValue) }
}
Run Code Online (Sandbox Code Playgroud)
但是,它也有willSet和didSet行动.这些在分别调用setter之前和之后调用.考虑到你可以在setter中使用相同的代码,它们的目的是什么?
我有一个非常基本的视图,仅显示TextField:
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
TextField("Enter a string...", text: $viewModel.string)
}
}
Run Code Online (Sandbox Code Playgroud)
的TextField文本绑定到string视图模型上的属性:
class ViewModel: ObservableObject {
@Published var string: String = "" {
didSet {
print("didSet string:", string)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我添加了一个didSet属性观察器,以便在字符串更改时执行自定义操作。对于这个简单的例子,我只在控制台上打印一个字符串。
当我运行此代码并在文本字段中输入字符串“123”时,这是我得到的输出:
didSet string: 1
didSet string: 1
didSet string: 12
didSet string: 12
didSet string: 123
didSet string: 123
Run Code Online (Sandbox Code Playgroud)
为什么?
为什么didSet我输入的每个字符都会调用两次闭包?(我希望每个角色都会调用一次。)
代码有什么问题或者这是预期的行为吗?
binding textfield property-observer swiftui observableobject
我正在对此进行测试,看起来如果你改变其中的值didSet,你就不会再接到另一个电话了didSet.
var x: Int = 0 {
didSet {
if x == 9 { x = 10 }
}
}
Run Code Online (Sandbox Code Playgroud)
我可以依靠吗?它在某处记录了吗?我没有在Swift编程语言文档中看到它.
我在我的类中添加了一个Timer变量,并使用其didSet观察器使旧值无效
var timer: Timer? {
didSet { oldValue?.invalidate() }
}
deinit {
timer = nil
}
Run Code Online (Sandbox Code Playgroud)
我认为这样就足以在类被取消初始化时使计时器无效,但看起来似乎没有调用didSet.这是为什么?观察员在去初始化期间不工作吗?
我想观察一个变量的值是否已经改变.我想知道Java是否有与Swift中的willSet和didSet方法相同的东西?
让我们从代码片段开始:
St Foo {
var proA: Int = 0 { // needs initialization
willSet {
print("about to set proA to \(newValue) from \(proA)")
}
didSet {
print("already set proA to \(proA) from \(oldValue)")
}
}
var ProB: Int { // do not needs initialization
return 1
}
}
let foo = Foo()
foo.proA = 23
print(foo.ProB)
Run Code Online (Sandbox Code Playgroud)
以下是我个人对存储和计算属性的一些理解:
a:只有观察者的属性(willSet 和 didSet)不是计算属性而是存储属性(例如上面代码中的proA属性)。
b:计算属性不能有初始化(见上面代码的注释)。
c: setter 相当于属性观察者,属性观察者只是变异前后的 setter + 观察者。
问题:
1.我想知道是什么使属性成为计算属性?只要该属性有一个 getter 并返回它就是一个计算属性,这是否正确?
2.我的所有理解(a, b & c)都正确吗?如果没有,请您指出来。
3. …
我试图在我的自定义UIViewController上实现属性观察器,但我注意到它没有使用isEditing属性.
你们有个想法为什么?
class MasterViewController: UIViewController {
// MARK: - Properties
override var isEditing: Bool {
didSet {
print("VC is editing")
}
}
}
Run Code Online (Sandbox Code Playgroud) 在回答如何知道数组中元素的值是否已更改的问题时受到启发?, 答案是使用Property Observer来检查数组是否已被修改。
但是,如何确定属性观察器中集合类型中更新的元素是什么?例如:
class MyClass {
var strings: [String] = ["hello", "world", "!"] {
didSet(modifiedStrings) {
print("strings array has been modified!!:")
print(modifiedStrings)
}
}
}
let myClass = MyClass()
myClass.strings.append("a string")
myClass.strings[0] = "Hello"
myClass.strings.removeLast()
Run Code Online (Sandbox Code Playgroud)
请注意,didSet每个添加、更新或删除操作都调用了代码,但我如何才能确切地知道受影响的元素是什么?甚至有没有办法通过将strings数组作为Property Observer来实现这一点?
我在询问 Swift 中的所有集合类型,因为我认为所有集合类型都应该具有相同的行为,这与观察有关。
谢谢。