注意在ARC环境下:
1、在类中
@property的本质:
@property = ivar(实例变量) + getter/setter方法声明 + getter/setter方法实现;
当在类中使用@property声明属性时,无论是在.h中的还是在.m中,
编译器会自动生成一个带下划线的实例变量 + 对应的getter/setter方法的声明 + 对应的getter/setter方法的实现;
例如:
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@end
此时,会给Person类的.h中默认添加一个名为_name的成员变量,setName和name:两个方法(getter/setter)的声明,如:
@interface Person : NSObject
{
NSString *_name;
}
- (void)setName:(NSString *)name;
- (NSString *)name;
@end
并且在Person类的.m中添加setName和name:两个方法(set/get)的实现,如:
- (void)setName:(NSString *)name{
_name = name;
}
- (NSString *)name{
return _name;
}
2、在分类中
@property的本质:
@property = getter/setter方法声明;
可以发现,当我们在分类中使用@property声明属性时,只是生成了getter/setter方法的声明,并不会自动生成ivar(实例变量) 和 getter/setter方法的实现。
例如:
@interface Person (test)
@property (nonatomic, copy) NSString *name;
@end
此时,只是在分类的.h中自动生成了setName和name:两个方法(set/get)的声明,如:
@interface Person (test)
- (void)setName:(NSString *)name;
- (NSString *)name;
@end
并且,在.m中有会提示:
提示需要提供setter/getter方法的实现;
如果,不提供setter/getter方法的实现,在使用是会报错unrecognized selector,
如下:
所以,一般我们会通过runtime添加关联对象,来间接的实现给分类添加属性。如下:
#import "Person+test.h"
#import <objc/runtime.h>
@implementation Person (test)
- (NSString *)name {
return objc_getAssociatedObject(self, @selector(name));
}
- (void)setName:(NSString *)name {
objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
@end
分类(Category)具体的实现原理,这里暂不详细说明;
网友评论