在Modern Objective-C运行时中,您可以执行以下操作:
@interface MyClass : NSObject {
}
@property NSString *stringProperty;
@end
@implementation MyClass
@synthesize stringProperty;
@end
这是我对现代运行时的理解,这不仅会合成我的属性的访问器,而且还会合成实例变量本身,所以我可以在这个类的方法之一[stringProperty length];
中说出它只会工作好像我已经宣布了一个实例变量。
我现在开始在我的所有代码中使用它,因为,我不得不一遍又一遍地写一遍。我听说过clang 2.0编译器,我甚至可以跳过@synthesize
(但这是另一回事)。但我一直在想,这样做的一些缺点是什么?除了我的属性,我真的需要一个实例变量吗?
我知道有时候我想保留一个变量私有而不能从外部访问它(但是我通常只是在我的私有类扩展中声明属性,或者我根本不创建它的属性,如果我不需要访问器)。
有时我不想这样做吗?
答案 0 :(得分:4)
可能建议不使用合成实例变量的一个可能原因是在当前版本的Xcode(3.2.5)中调试它们有点麻烦。在通过GDB运行代码时,它们似乎没有出现在实时调试器视图中,获取它们的唯一方法是通过gdb控制台,如po [0xOBJ_ADDRESS propertyName]
。不如标准的非合成ivar那么好。
也许Xcode 4解决了这个问题,但是我没有足够的经验说它(它仍然在NDA下)。
有关此SO问题的更多信息:Seeing the value of a synthesized property in the Xcode debugger when there is no backing variable
答案 1 :(得分:3)
您可能希望为单个实例变量提供许多属性,例如:
在这些情况下,您不希望合成实例变量(它已经存在)或访问器方法(您希望提供它们来进行转换)。
答案 2 :(得分:1)
任何时候你需要在类中进行转换(除非有人知道更好的方法),你需要序列化。例如,如果您有一个具有数值的类。您无法序列化整数,因此您将其存储为类中的NSNumber,但属性是整数类型。
另一个例子是,如果您在使用CoreData时按照Apple的建议进行编码。他们说你应该创建一个从NSManagedObject派生的自定义类作为托管对象的类,并为每个属性使用一个属性。那么你将使用@dynamic而不是@synthesize,并且根本不需要iVar。
答案 3 :(得分:1)
但是我一直在想,这样做有什么缺点?除了我的属性,我真的需要一个实例变量吗?
可能的原因:
init
和dealloc
中的实例变量,而不会跳过子类覆盖或KVO。我不确定第一点到底有多有效。围绕这些问题可能还有其他方法。如果你需要支持更老的Mac,第二点就是游戏结束。
答案 4 :(得分:0)
另一个原因是避免直接变量访问的快捷方式。
我尝试遵循个人编码惯例: - 对象变量:前缀为下划线'_xxx' - property:不带下划线命名'xxx'
这确保我永远不会无意中写出像
这样的东西xxx = value;
或
[xxx someMessage];
我想总是使用getter / setter。
self.xxx = value;
[self.xxx someMessage];
当您对对象变量使用lazy init时,这尤其有用......