调用属性设置器时,响应数据更改的最佳方法是什么。例如,如果我有一个名为data
的属性,我怎样才能在调用[object setData:newData]
时做出反应并仍然使用合成的setter。本能地,我会像这样覆盖合成的setter:
- (void)setData:(DataObject *)newData {
// defer to synthesised setter
[super setData:newData];
// react to new data
...
}
...但当然这没有意义 - 我不能像这样使用super
。那么处理这种情况的最佳方法是什么?我应该使用KVO吗?或其他什么?
答案 0 :(得分:4)
根据您想要的控制程度,有几种不同的方法可以做到这一点。一种方法是观察你自己的财产:
[self addObserver:self forKeyPath:@"data" options:0 context:nil];
- (void)observeValueForKeyPath:(NSString *)path ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if(object == self && [path isEqualToString:@"data"]) {
//handle change here
} else [super observeValueForKeyPath:path ofObject:object change:change context:context];
}
确保在dealloc或finalize方法中将自己移除为观察者,如果不是之前的话。
另一种方法是覆盖-didChangeValueForKey:
。但是,如果对象上没有观察者,则可能无法调用此方法。
- (void)didChangeValueForKey:(NSString *)key {
[super didChangeValueForKey:key];
if([key isEqualToString:@"data"]) {
//handle change here
}
}
答案 1 :(得分:2)
@synthesize创建默认访问器以便于使用。如果需要一些特殊操作,那么总是可以编写自己的访问器而不是使用@synthesize。 setter和getter不是从基类继承的,它们是由@synthesize指令创建的。所以你不需要(你也不能)调用super setData :(除非你真的创建了支持它的超类)。
确保正确管理内存。 Memory Management Programming Guide包含有关如何管理不同类型内存策略的内存(保留或分配或复制)的示例。
答案 2 :(得分:0)
您可以定义合成的“私有”属性(将其放在.m
文件中)
@interface ClassName ()
// Declared properties in order to use compiler-generated getters and setters
@property (nonatomic, strong <or whatever>) NSObject *privateSomeObject;
@end
然后在ClassName
(.h
和@implementation
部分)的“公开”部分手动定义一个getter和setter,就像这样,
- (void) setSomeObject:(NSObject *)someObject {
self.privateSomeObject = someObject;
// ... Additional custom code ...
}
- (NSArray *) someObject {
return self.privateSomeObject;
}
您现在可以照常访问someObject
“属性”,例如object.someObject
。您还可以获得自动生成retain
/ release
/ copy
的优势,与ARC的兼容性,几乎不会失去线程安全性。