1.理解屬性這一概念
首先我們應(yīng)當理解屬性這一概念,看如下代碼:
@interface Father : NSObject
{
@public
NSString * name1;
@private
NSString * name2;
@protected
NSString * name3;
}
@end
在OC的類中我們當然可以這樣聲明屬性,但是這樣的寫法是有一定的問題的,這些屬性的存儲方式都是在實力對象中,當我們通過對象指針訪問屬性值的時候,內(nèi)存中是通過屬性值偏移對象首地址的位數(shù)進行查找相對應(yīng)的屬性,這樣一來就會有一個問題。
如果我們在類中添加新的屬性的時候,就要重新編譯才能重新定義屬性的偏移量,這種”硬編碼“,在我們用老版本的類聲明替換新版本的過程當中,就會出現(xiàn)屬性值訪問出現(xiàn)錯誤的現(xiàn)象。
當然,這在OC中也給出了相應(yīng)的解決方法,此時我們就用到@preoperty了。
@interface Father : NSObject
@property NSString * name1;
@property NSString * name2;
@end
這樣聲明屬性屬性的訪問會變成動態(tài)的,對于之前的”硬編碼“,OC就會把之前的偏移量轉(zhuǎn)換到相應(yīng)的類對象中,這樣一來,每次訪問屬性就會到類對象中去尋找相應(yīng)的變量,這樣一來就會在執(zhí)行的時候,確定屬性的地址,從而就不會出現(xiàn)之前的錯誤。
使用@property還會幫我們制動生成setter和getter方法(再此就不過多闡述)
改變生成的屬性的名字。
@implementation Father
@synthesize name1 = name11;
@synthesize name2 = name22;
@end
告訴編譯器不要生成相應(yīng)的setter和getter放法(使用點語法在編譯的時候不會報錯,但執(zhí)行的時候會出錯)。
@implementation Father
@dynamic name1,name2;
@end
關(guān)于@property的參數(shù)簡單分類一下:原子性與非原子性(atomicity、nonatomic)、讀寫權(quán)限(readwrite、readonly)、內(nèi)存管理語句(assign、strong、copy、weak、unsafe_unretained)、方法名設(shè)置(setter=<name> getter=<name>)。
這些屬性不過多介紹,強調(diào)一下copy對封裝性的保護:
@interface Father : NSObject
@property (nonatomic,copy) NSString * name;
@end
Father * father = [[Father alloc]init];
NSMutableString * str = [NSMutableString stringWithString:@"nihao"];
father.name = str;
[str appendString:@"haha"];
NSLog(@"str---%@",str);
NSLog(@"father.name---%@",father.name);
打印結(jié)果:

使用copy對屬性進行了保護,換句話說就是我們只能通過set屬性改變屬性的值,而不希望str改變的時候?qū)傩愿淖?,下面來看下面的例?/p>
@interface Father : NSObject
@property (nonatomic,strong) NSString * name;
@end
Father * father = [[Father alloc]init];
NSMutableString * str = [NSMutableString stringWithString:@"nihao"];
father.name = str;
[str appendString:@"haha"];
NSLog(@"str---%@",str);
NSLog(@"father.name---%@",father.name);
打印結(jié)果:

由此我們可以看出,在改變str的時候?qū)傩灾狄哺淖兞耍@樣就破壞了封裝性,因此要使用copy。
另外一點,在重寫構(gòu)造方法的時候也要保持相應(yīng)的屬性管理方法。
簡單的舉個例子:
- (instancetype)initWithName:(NSString *)name{
if (self = [super init]) {
_name = [name copy];
}
return self;
}
如果直接賦值的話,也會出現(xiàn)破壞封裝性的現(xiàn)象,因此應(yīng)當注意。
還是要注意一點,千萬不要在構(gòu)造方法里面調(diào)用setter或者getter方法,接下來會詳細介紹。
2.在對象內(nèi)部盡量直接訪問實例變量
對于訪問實例變量的方法說法不一,有的強調(diào)使用屬性方法進行訪問,有的強調(diào)直接使用變量。總結(jié)下來,覺得在對象內(nèi)部盡量直接使用變量,這樣可以降低程序開銷,但也分幾種情況,下面簡單總結(jié)如下:
- 在初始化方法中訪問實例變量直接引用
- 在對象內(nèi)部讀取數(shù)據(jù)的時候直接訪問實例變量
- 在寫入數(shù)據(jù)的時候通過屬性進行訪問
- 如果是通過懶加載方法那么久必須要用屬性來訪問了
未完待繼。。。。。。