iOS KVO - 检测何时再次设置相同的值
iOS KVO - detect when the same value is set again
是否可以通过一种方式使用 KVO,它不仅可以检测值是否更改,还可以检测是否再次设置了相同的值?我目前仅在值更改(与之前设置的不同)时才收到通知。每次设置值时我都需要收到通知(即使它与之前设置的值相同)。我怎样才能做到这一点?
我的代码:
private func addObserver() {
defaults.addObserver(self, forKeyPath: DefaultsKeys.testKey._key, options: .new, context: nil)
}
public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard let value = change?[NSKeyValueChangeKey.newKey] as? Bool else { return }
statusCallback?(value)
}
private func removeObserver() {
defaults.removeObserver(self, forKeyPath: DefaultsKeys.testKey._key)
}
您可以通过以下方式实现:
public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
let value = change?[.oldKey] as? Bool
guard value == nil || value != yourVariableToCheck else { return }
statusCallback?(value)
}
仅在您自己的变量上更改 yourVariableToCheck。
KVO 机制非常简单 - 它不会在设置新值时执行任何额外检查,它仅在调用 setter 时触发。因此,无法区分该值是否与已设置的值不同。 这很好。首先,因为在实践中,将相同的值赋给一个变量并不常见。
其次,引入额外的检查是消耗品,在大多数情况下是不需要的。如果存在该检查,则会对性能产生负面影响。
也就是说,就 Swift 而言,您可以考虑用本地 Swift 属性 观察者替换 KVO 机制(本质上是 Objective-C 遗留物) : willSet
和 didSet
。这基本上与传递两个选项所起的作用相同:NSKeyValueObservingOptionNew
和 NSKeyValueObservingOptionOld
(Swift 中的 .old
和 .new
)到 addObserver
方法。一旦指定了这些标志,无论何时触发 KVO 机制,您都将在 observeValue(...)
中收到两个值(旧值和新值),您可以从中决定如何处理其中任何一个。但是,当 willSet
的功能几乎相同并且更方便时,为什么您需要如此复杂:
var myVariable : String! {
willSet {
print("Old value is: \(myVariable)")
print("New value is: \(newValue)")
// Let's do something with our old value
}
didSet {
print("Just set the new value: \(newValue)")
// New value is set. Let's do some actions.
}
}
KVO 通常 是 每次设置观察到的 属性 时调用,即使它与上次的值相同。但我猜你正在观察 UserDefaults
,它有一个特性可以防止这种情况发生(可能是一种优化,可以防止不必要的商店保存)。
您可以注册.didChangeNotification
,无论值是否改变,都显示调用:
NotificationCenter.default.addObserver(forName: UserDefaults.didChangeNotification, object: nil, queue: .main) { notification in
print("notification", notification)
}
如果要跟踪NSUserDefaults
中的每个设置值,即使新值与之前的值相同,用NSDictionary
包裹值,并在字典中放入NSUUID
值,每次作为新的 setValue
被调用时生成。
之前(observeValueForKeyPath
没有调用每个 setValue
):
[self.mySharedDefaults setValue: @"CHECKING" forKey:@"appStatusOUT"];
之后(observeValueForKeyPath
每 setValue
被调用):
[self.mySharedDefaults setValue: [NSDictionary dictionaryWithObjectsAndKeys: @"CHECKING", @"CMD",
[NSUUID UUID].UUIDString, @"UUID", nil] forKey:@"appStatusOUT"];
是否可以通过一种方式使用 KVO,它不仅可以检测值是否更改,还可以检测是否再次设置了相同的值?我目前仅在值更改(与之前设置的不同)时才收到通知。每次设置值时我都需要收到通知(即使它与之前设置的值相同)。我怎样才能做到这一点?
我的代码:
private func addObserver() {
defaults.addObserver(self, forKeyPath: DefaultsKeys.testKey._key, options: .new, context: nil)
}
public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard let value = change?[NSKeyValueChangeKey.newKey] as? Bool else { return }
statusCallback?(value)
}
private func removeObserver() {
defaults.removeObserver(self, forKeyPath: DefaultsKeys.testKey._key)
}
您可以通过以下方式实现:
public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
let value = change?[.oldKey] as? Bool
guard value == nil || value != yourVariableToCheck else { return }
statusCallback?(value)
}
仅在您自己的变量上更改 yourVariableToCheck。
KVO 机制非常简单 - 它不会在设置新值时执行任何额外检查,它仅在调用 setter 时触发。因此,无法区分该值是否与已设置的值不同。 这很好。首先,因为在实践中,将相同的值赋给一个变量并不常见。
其次,引入额外的检查是消耗品,在大多数情况下是不需要的。如果存在该检查,则会对性能产生负面影响。
也就是说,就 Swift 而言,您可以考虑用本地 Swift 属性 观察者替换 KVO 机制(本质上是 Objective-C 遗留物) : willSet
和 didSet
。这基本上与传递两个选项所起的作用相同:NSKeyValueObservingOptionNew
和 NSKeyValueObservingOptionOld
(Swift 中的 .old
和 .new
)到 addObserver
方法。一旦指定了这些标志,无论何时触发 KVO 机制,您都将在 observeValue(...)
中收到两个值(旧值和新值),您可以从中决定如何处理其中任何一个。但是,当 willSet
的功能几乎相同并且更方便时,为什么您需要如此复杂:
var myVariable : String! {
willSet {
print("Old value is: \(myVariable)")
print("New value is: \(newValue)")
// Let's do something with our old value
}
didSet {
print("Just set the new value: \(newValue)")
// New value is set. Let's do some actions.
}
}
KVO 通常 是 每次设置观察到的 属性 时调用,即使它与上次的值相同。但我猜你正在观察 UserDefaults
,它有一个特性可以防止这种情况发生(可能是一种优化,可以防止不必要的商店保存)。
您可以注册.didChangeNotification
,无论值是否改变,都显示调用:
NotificationCenter.default.addObserver(forName: UserDefaults.didChangeNotification, object: nil, queue: .main) { notification in
print("notification", notification)
}
如果要跟踪NSUserDefaults
中的每个设置值,即使新值与之前的值相同,用NSDictionary
包裹值,并在字典中放入NSUUID
值,每次作为新的 setValue
被调用时生成。
之前(observeValueForKeyPath
没有调用每个 setValue
):
[self.mySharedDefaults setValue: @"CHECKING" forKey:@"appStatusOUT"];
之后(observeValueForKeyPath
每 setValue
被调用):
[self.mySharedDefaults setValue: [NSDictionary dictionaryWithObjectsAndKeys: @"CHECKING", @"CMD",
[NSUUID UUID].UUIDString, @"UUID", nil] forKey:@"appStatusOUT"];