我可以覆盖@synthesize在Objective C中的工作方式吗?

时间:2009-09-16 14:26:10

标签: objective-c cocoa-touch

我正在创建一个具有isDirty标志的基类。它在其属性之一的任何时候都会更改,但由于它是基类,因此它不知道它的属性是什么。所以基本上,在每个子类上,我必须覆盖每个- set:方法,如下所示:

- (id) setName:(NSString *)value {
  if ([name isEqualToString:value]) {
    return;
  }
  [name autorelease];
  name = [value retain];
  isDirty = YES;  //Here's the important bit
}

几乎每一行都是自动合成的setter所能做的。有什么方法可以覆盖@synthesize实际创建的内容吗?

我已经提出了其他选项,但它们看起来在运行时比这种方法慢得多。我已经考虑过添加一个对象来观察它自己的属性更改,或创建一个通用函数来完成所有这些并将地址传递给iVar和新值,但仍然需要覆盖setter。

有什么想法吗?如果它有所作为,它适用于iPhone应用程序。

4 个答案:

答案 0 :(得分:8)

这里有几个问题:

(1)如果您担心setter性能,则不应在setter中使用-isEqualToString :.做一个指针比较,因为在这种情况下这一切都很重要。

(2)如果你有一个NSString属性,你应该复制set。复制对于不可变字符串是免费的,并且会将你的培根保存为可变字符串(通过防止调用者从你下面改变字符串)。

(3)再次表现;你检查了相等,但然后使用autorelease。这会产生不必要的开销。

(4)*它们似乎在运行时会慢得多*表示您实际上没有尝试过,没有发现性能问题,并且过早地优化了代码。给定(1)和(3),可能更容易解决性能问题。

我的建议:

(1)使用@synthesize。它将生成正确和快速的代码,解决(1)和(3)。

(2)使用KVO或其他机制之一。在通过仪器和量化确定性能问题之前,您没有性能问题。

(3)考虑使用CoreData(当然,除非你的目标是OS 2.x)。示例代码来自显然是模型对象的东西。如果您的代码很好地考虑到模型/视图/控制器中,那么在模型层使用CoreData可以简化您的应用程序,而CoreData可以很好地完成变更跟踪。

答案 1 :(得分:7)

我无法知道这会让你覆盖@synthesize所做的事情。

在一天结束时,它用于创建基本的访问方法 - 即。那些没有特定行为的人。

也许你应该研究关键价值编码和关键价值观察?

答案 2 :(得分:3)

没有。

只有深入挖掘Objective-C runtime或使用proxy objects,才能实现您想要实现的目标。

你为什么不再看看KVO?

答案 3 :(得分:1)

如果您编写自己的访问方法,@synthesize会尊重它。 @synthesize优先考虑您自己编写的访问器。只需提供您喜欢的访问者,就可以忽略@synthesize。例如,您可以实现一个只在不存在属性时才创建属性的访问器。

示例:

@synthesize standardUserDefaults;

- (NSUserDefaults *)standardUserDefaults {
    NSLog(@"standardUserDefaults");
    if (!standardUserDefaults) {
        NSLog(@"standardUserDefaults new");
        self.standardUserDefaults = [NSUserDefaults standardUserDefaults];
    }
    return standardUserDefaults;
}

这里“合成器”是合成的,而“吸气器”不合成。