4

在 Modern Objective-C 运行时中,您可以执行以下操作:

@interface MyClass : NSObject {
}
@property NSString *stringProperty;
@end

@implementation MyClass
@synthesize stringProperty;
@end

这是我对现代运行时的理解,这不仅会合成我的属性的访问器,还会合成实例变量本身,所以我可以在这个类的方法之一中[stringProperty length];说它就像我声明了一个实例一样工作多变的。

我现在已经开始在我的所有代码中使用它,因为,这是我必须一遍又一遍地编写的东西。而且我听说过使用 clang 2.0 编译器,我什至可以跳过@synthesize(但那是另一回事)。但我一直在想,这样做有什么缺点?除了我的属性之外,我什么时候真正需要一个实例变量?

我知道有时我想保持一个变量私有而不是从外部访问它(但是我通常只是在我的私有类扩展中声明该属性,或者我根本不为它创建一个属性,如果我不需要访问器)。

有没有什么时候我不想这样做?

4

5 回答 5

4

建议不使用合成实例变量的一个可能原因是在当前版本的 Xcode (3.2.5) 中调试它们有点麻烦。当通过 GDB 运行代码时,它们似乎没有出现在实时调试器视图中,获得它们的唯一方法是通过 gdb 控制台,如po [0xOBJ_ADDRESS propertyName]. 不如标准的、非合成的 ivar 好。

也许 Xcode 4 解决了这个问题,但我没有足够的经验可以说(而且它仍在 NDA 之下)。

有关此 SO 问题的更多信息:在没有支持变量时在 Xcode 调试器中查看合成属性的值

于 2010-12-07T21:23:02.270 回答
3

您可能希望为单个实例变量提供许多属性,例如:

  • 用于访问以度数和弧度为单位的角度值
  • 用于访问直角坐标系和极坐标系中的坐标

在这些情况下,您不想合成实例变量(它已经存在)或访问器方法(您想提供它们进行转换)。

于 2010-12-07T21:01:31.427 回答
1

任何时候您需要在需要序列化的类中进行转换(除非有人知道更好的方法)。例如,如果您有一个具有数值的类。您不能序列化整数,因此您将其作为 NSNumber 存储在类中,但该属性是整数类型。

另一个例子是,如果您在使用 CoreData 时按照 Apple 的建议进行编码。他们说您应该创建一个从 NSManagedObject 派生的自定义类作为托管对象的类,并为每个属性使用一个属性。然后,您将使用 @dynamic 而不是 @synthesize 并且根本不需要 iVar。

于 2010-12-07T21:10:52.983 回答
1

但我一直在想,这样做有什么缺点?除了我的属性之外,我什么时候真正需要一个实例变量?

可能的原因:

  • 它允许您更改实例变量,initdealloc不会绊倒子类覆盖或 KVO。
  • 该应用程序将在 Mac OS X 上以 32 位模式编译和运行。仍然有一些英特尔 Mac 不支持 64 位。

我不确定第一点的有效性。可能有其他方法可以解决这些问题。如果您需要支持较旧的 Mac,第二点是游戏结束。

于 2010-12-08T11:43:12.470 回答
0

另一个原因是避免直接访问变量的捷径。

我尝试遵循个人编码约定:-对象变量:带下划线'_xxx'的前缀-属性:命名时不带下划线'xxx'

这确保我永远不会无意中写出类似的东西

xxx = value;

或者

[xxx someMessage];

我想始终使用 getter/setter。

self.xxx = value;
[self.xxx someMessage];

当您对对象变量使用惰性初始化时,这特别有用......

于 2010-12-08T09:48:04.820 回答