对每个 属性 变化做点什么
Do something on each property change
我的 class 中有几个属性,我想在每次 属性 更改时调用 saveToFile
。
我不想覆盖每个 属性 的 setter。我应该覆盖吗
-[NSObject methodForSelector]
?最好的方法是什么?
阅读 属性 观察员。 Swift中的示例:
var currentSession: Session? {
didSet {
if let session = self.currentSession {
// Write session to file.
}
}
}
对于Objective-C,key-value observing可能更合适。
您想要的是键值观察或 KVO。
例如,您注册了一个每次 属性 更改时都会调用的方法。
如果您有一个文本字段并且想听取其文本的变化,您可以这样注册
[self.textField addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:nil];
并且在您的 class 中,您将实现此方法:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if ([keyPath isEqualToString:@"text"]) {
NSLog(@"Textfield changed - MAKE CHANGES HERE");
}
}
如果您不熟悉 KVO,这里有一个很好的教程:
http://www.appcoda.com/understanding-key-value-observing-coding/
您可以注册为您想要监控的属性的观察者。 Cocoa's KVO 功能将在此处为您提供帮助。
基本上您需要调用 addObserver:forKeyPath:options:context:
并注册以便在属性更改时收到通知。发生这种情况时,运行时会在注册为观察者的对象上调用 observeValueForKeyPath:ofObject:change:context:
方法。你可以在这里做你想做的节省。
注册示例:
for(NSString *propName in self.propsIWantMonitored) {
[self addObserver:self forKeyPath:propName change:0 context:@selector(saveToFile)];
}
以及处理 prop 值的变化:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
// make sure we don't interfere with other observed props
// and check the context param
if (context == @selector(saveToFile)) {
[self saveToFile];
}
}
以及注销:
for(NSString *propName in self.propsIWantMonitored) {
[self removeObserver:self forKeyPath:propName context:@selector(saveToFile)];
}
上面的代码示例假设您已经声明了一组要监视的属性,您可以使用这些属性注册为观察者。您使用 context
参数来确定 observeValueForKeyPath
是否被调用作为对您刚刚注册的观察者的响应,以免与您的其他部分进行的其他 KVO 注册发生冲突 class.
解决您问题的替代方法(更节能)
上述方法有一个注意点:如果连续设置多个属性,那么saveToFile
方法会在短时间内被多次调用,这可能会造成性能瓶颈并增加能源消耗您的应用程序。
另一种方法是设置一个 dirty
标志,该标志在 observeValueForKeyPath:
中设置并在 saveToFile
中重置。你可以saveToFile
检查标志,如果对象不脏就不要使用文件系统。
您可以安排一个定期调用 saveToFile
的计时器,这样一次设置多个属性将导致只有一个磁盘访问。当您想要立即保存时,您可以随时手动调用 saveToFile
。
注意。我指的定时器是 GCD timer,因为 NSTimer 也会对您的应用程序产生负面能量影响。
我的 class 中有几个属性,我想在每次 属性 更改时调用 saveToFile
。
我不想覆盖每个 属性 的 setter。我应该覆盖吗
-[NSObject methodForSelector]
?最好的方法是什么?
阅读 属性 观察员。 Swift中的示例:
var currentSession: Session? {
didSet {
if let session = self.currentSession {
// Write session to file.
}
}
}
对于Objective-C,key-value observing可能更合适。
您想要的是键值观察或 KVO。 例如,您注册了一个每次 属性 更改时都会调用的方法。
如果您有一个文本字段并且想听取其文本的变化,您可以这样注册
[self.textField addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:nil];
并且在您的 class 中,您将实现此方法:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if ([keyPath isEqualToString:@"text"]) {
NSLog(@"Textfield changed - MAKE CHANGES HERE");
}
}
如果您不熟悉 KVO,这里有一个很好的教程: http://www.appcoda.com/understanding-key-value-observing-coding/
您可以注册为您想要监控的属性的观察者。 Cocoa's KVO 功能将在此处为您提供帮助。
基本上您需要调用 addObserver:forKeyPath:options:context:
并注册以便在属性更改时收到通知。发生这种情况时,运行时会在注册为观察者的对象上调用 observeValueForKeyPath:ofObject:change:context:
方法。你可以在这里做你想做的节省。
注册示例:
for(NSString *propName in self.propsIWantMonitored) {
[self addObserver:self forKeyPath:propName change:0 context:@selector(saveToFile)];
}
以及处理 prop 值的变化:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
// make sure we don't interfere with other observed props
// and check the context param
if (context == @selector(saveToFile)) {
[self saveToFile];
}
}
以及注销:
for(NSString *propName in self.propsIWantMonitored) {
[self removeObserver:self forKeyPath:propName context:@selector(saveToFile)];
}
上面的代码示例假设您已经声明了一组要监视的属性,您可以使用这些属性注册为观察者。您使用 context
参数来确定 observeValueForKeyPath
是否被调用作为对您刚刚注册的观察者的响应,以免与您的其他部分进行的其他 KVO 注册发生冲突 class.
解决您问题的替代方法(更节能)
上述方法有一个注意点:如果连续设置多个属性,那么saveToFile
方法会在短时间内被多次调用,这可能会造成性能瓶颈并增加能源消耗您的应用程序。
另一种方法是设置一个 dirty
标志,该标志在 observeValueForKeyPath:
中设置并在 saveToFile
中重置。你可以saveToFile
检查标志,如果对象不脏就不要使用文件系统。
您可以安排一个定期调用 saveToFile
的计时器,这样一次设置多个属性将导致只有一个磁盘访问。当您想要立即保存时,您可以随时手动调用 saveToFile
。
注意。我指的定时器是 GCD timer,因为 NSTimer 也会对您的应用程序产生负面能量影响。