@property用来定义变量的属性,定义的变量会自动声明变量,自动生成setter方法和getter方法,便于变量的操作,常用的修饰词是nonatomic,strong,readwrite等。
通过clang的方法查看@property生成的变量和方法如下:
写一个属性
@interface Property ()
@property(nonatomic, copy) NSString * myName;
@end
执行clang命令
clang -rewrite-objc Property.m
得到.cpp文件,其中变量和方法的部分如下
我们创建的类为MyProperty,MyProperty_IMPL为类的实现,可以看到系统自动生成的变量_myName
typedef struct objc_object MyProperty;
typedef struct {} _objc_exc_MyProperty;
#endif
extern "C" unsigned long OBJC_IVAR_$_MyProperty$_myName;
struct MyProperty_IMPL {
struct NSObject_IMPL NSObject_IVARS;
NSString *_myName;
};
static NSString * _I_MyProperty_myName(MyProperty * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_MyProperty$_myName)); }
extern "C" __declspec(dllimport) void objc_setProperty (id, SEL, long, id, bool, bool);
static void _I_MyProperty_setMyName_(MyProperty * self, SEL _cmd, NSString *myName) { objc_setProperty (self, _cmd, __OFFSETOFIVAR__(struct MyProperty, _myName), (id)myName, 0, 1); }
将自动生成的ivar和method加入列表
static struct /*_ivar_list_t*/ {
unsigned int entsize; // sizeof(struct _prop_t)
unsigned int count;
struct _ivar_t ivar_list[1];
} _OBJC_$_INSTANCE_VARIABLES_MyProperty __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_ivar_t),
1,
{{(unsigned long int *)&OBJC_IVAR_$_MyProperty$_myName, "_myName", "@\"NSString\"", 3, 8}}
};
static struct /*_method_list_t*/ {
unsigned int entsize; // sizeof(struct _objc_method)
unsigned int method_count;
struct _objc_method method_list[4];
} _OBJC_$_INSTANCE_METHODS_MyProperty __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_objc_method),
4,
{{(struct objc_selector *)"myName", "@16@0:8", (void *)_I_MyProperty_myName},
{(struct objc_selector *)"setMyName:", "v24@0:8@16", (void *)_I_MyProperty_setMyName_},
{(struct objc_selector *)"myName", "@16@0:8", (void *)_I_MyProperty_myName},
{(struct objc_selector *)"setMyName:", "v24@0:8@16", (void *)_I_MyProperty_setMyName_}}
};
从.cpp文件可以看到,@property会在编译阶段自动生成ivar成员变量"_myName"
、getter方法"myName"
和setter方法"setMyName:"
{
NSString *_myName;
}
- (void)setMyName:(NSString *)myName;
- (NSString *)myName;
nonatomic是非原子性,修饰的变量不会对setter方法加锁,属于非线程安全,但是运行速度快,适合用于移动设备上;
atomic是原子性,对setter方法加锁,具有线程安全,但是会消耗大量资源
系统默认修饰是atomic,所以在声明变量时需要指定nonatomicassign修饰整形变量
strong是强引用
copy是复制属性
weak是弱引用,避免循环引用会使用weakreadwrite是可读可写,自动生成setter和getter方法
readonly为只读状态,只会生成getter方法
调用属性的setter方法会触发键值观测
_myName = "ella"; //该操作是赋值操作,不会触发键值观测
self.myName = "ella"; //该操作调用的是setter方法,会触发键值观测