@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方法,會觸發鍵值觀測