屬性@property探索

  1. @property用來定義變量的屬性,定義的變量會自動聲明變量,自動生成setter方法和getter方法,便於變量的操作,常用的修飾詞是nonatomic,strong,readwrite等。

  2. 通過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;
  1. nonatomic是非原子性,修飾的變量不會對setter方法加鎖,屬於非線程安全,但是運行速度快,適合用於移動設備上;
    atomic是原子性,對setter方法加鎖,具有線程安全,但是會消耗大量資源
    系統默認修飾是atomic,所以在聲明變量時需要指定nonatomic

  2. assign修飾整形變量
    strong是強引用
    copy是複製屬性
    weak是弱引用,避免循環引用會使用weak

  3. readwrite是可讀可寫,自動生成setter和getter方法
    readonly爲只讀狀態,只會生成getter方法
    調用屬性的setter方法會觸發鍵值觀測

_myName = "ella";         //該操作是賦值操作,不會觸發鍵值觀測
self.myName = "ella";    //該操作調用的是setter方法,會觸發鍵值觀測
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章