属性的自定义实现
上一章中我们提到的代码中有两个关键字@synthesize
和@dynamic
。@dynamic
意思是由开发人员提供相应的代码:对于只读属性需要提供 setter,对于读写属性需要提供 setter 和 getter。@synthesize
意思是,除非开发人员已经做了,否则由编译器生成相应的代码,以满足属性声明。对于上次的例子,如果开发人员提供了-(NSString*)registration
,编译器就会选择这个实现,不会用新的覆盖。因此,我们可以让编译器帮我们生成代码,以简化我们自己的代码输入量。最后,如果编译期没有找到访问器,而且没有使用@synthesize
声明,那么它就会在运行时添加进来。这同样可以实现属性的访问,但是即使这样,访问器的名字也需要在编译期决定。如果运行期没有找到访问器,就会触发一个异常,但程序不会停止,正如同方法的缺失。当我们使用@synthesize
时,编译器会被要求绑定某一特定的数据成员,并不一定是一样的名字。
@interface A : NSObject { int _foo; } @property int foo; @end @implementation A @synthesize foo=_foo; // 绑定 "_foo" 而不是 "foo" @end
访问属性的语法
为获取或设置属性,我们使用点号:这同简单的 C 结构是一致的,也是在 keypath 中使用的语法,其性能与普通方法调用没有区别。
@interface A : NSObject { int i; } @property int i; @end @interface B : NSObject { A* myA; } @property(retain) A* a; @end ... A* a = ... B* b = ...; a.i = 1; // 等价于 [a setI:1]; b.myA.i = 1;// 等价于 [[b myA] setI:1];
请注意上面例子中 A 类的使用。self->i
和self.i
是有很大区别的:self->i
直接访问数据成员,而self.i
则是使用属性机制,是一个方法调用。
高级细节
64 位编译器上,Objective-C 运行时环境与 32 位有一些不同。关联到@property
的实例数据可能被忽略掉,例如被视为隐式的。更多细节请阅读 Apple 的文档。
1 个评论
老兄 能帮我看看这个问题吗?
http://www.cocoachina.com/bbs/read.php?tid-53543.html