回应二传手

时间:2011-01-17 05:47:16

标签: objective-c cocoa

调用属性设置器时,响应数据更改的最佳方法是什么。例如,如果我有一个名为data的属性,我怎样才能在调用[object setData:newData]时做出反应并仍然使用合成的setter。本能地,我会像这样覆盖合成的setter:

- (void)setData:(DataObject *)newData {
    // defer to synthesised setter
    [super setData:newData];

    // react to new data
    ...
}

...但当然这没有意义 - 我不能像这样使用super。那么处理这种情况的最佳方法是什么?我应该使用KVO吗?或其他什么?

3 个答案:

答案 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)

来自this SO answer

您可以定义合成的“私有”属性(将其放在.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的兼容性,几乎不会失去线程安全性。