對(duì)象,消息姐扮,運(yùn)行期
理解“屬性”這一概念
OC是通過運(yùn)行時(shí)機(jī)制來提供相關(guān)支持的抽活,屬性則是用來封裝OC對(duì)象中數(shù)據(jù)的類型,可以自動(dòng)生成setter和getter方法荞膘,與其他非運(yùn)行時(shí)語言所不同的是罚随,類似于Java的語言在編譯期就已經(jīng)確定了成員變量在內(nèi)存中的作用域,通過偏移量(該變量距離起始位置的距離)來查找該變量羽资,而添加新的成員變量會(huì)導(dǎo)致異常淘菩,指向的變量出現(xiàn)錯(cuò)亂。
OC對(duì)這種情況的應(yīng)對(duì)方法是:將實(shí)例變量當(dāng)作一種存儲(chǔ)偏移量的特殊變量交給類對(duì)象來管理屠升,偏移量會(huì)在運(yùn)行期查找潮改,如果類進(jìn)行變動(dòng),那么存儲(chǔ)的偏移量也會(huì)變動(dòng)腹暖。
對(duì)象內(nèi)部盡量訪問實(shí)例變量
作者建議在對(duì)象內(nèi)部訪問成員變量時(shí)汇在,讀取數(shù)據(jù)建議直接訪問成員變量,而設(shè)置數(shù)據(jù)的時(shí)候脏答,使用內(nèi)部的setter方法糕殉。
- 因?yàn)樵L問getter方法時(shí)會(huì)經(jīng)過OC的消息派發(fā)中心,而直接訪問成員變量則會(huì)直接在內(nèi)存中找到該區(qū)域以蕴,相應(yīng)較快
- 設(shè)置數(shù)據(jù)時(shí)直接訪問成員變量會(huì)繞過內(nèi)存管理語義糙麦,例如copy的變量不會(huì)拷貝該屬性,造成內(nèi)存管理的異常
- 直接訪問實(shí)例變量不會(huì)觸發(fā)KVO丛肮,有可能會(huì)有問題
- 可以在setter和getter方法中添加斷點(diǎn)進(jìn)行代碼檢測(cè)赡磅,方便觀察
- 在懶加載中,必須使用存取方法來設(shè)置宝与,否則永遠(yuǎn)不會(huì)初始化成功
- 在初始化方法中焚廊,因?yàn)橛锌赡軙?huì)被子類重寫存取方法,所以要直接訪問成員變量
理解“對(duì)象等同性”這一概念
比較對(duì)象的等同行习劫,有“==” 和 isEqual 兩種方法咆瘟,第一種是比較的兩者的內(nèi)存地址,第二種比較的是內(nèi)容诽里。
以“類族模式”隱藏實(shí)現(xiàn)細(xì)節(jié)
類族模式是提供一個(gè)基類的接口負(fù)責(zé)實(shí)例化某對(duì)象袒餐,通過其中的邏輯判斷創(chuàng)建不同的字類對(duì)象,所以:創(chuàng)建出來的對(duì)象并非該類型。使用“==”判斷恒定為假值灸眼。在系統(tǒng)的一些類族中卧檐,創(chuàng)建子類需要手動(dòng)覆寫其規(guī)定的方法,例如NSarray中需要覆寫count焰宣,objectAtIndex方法霉囚。
在既有類中使用關(guān)聯(lián)對(duì)象存放自定義數(shù)據(jù)
在系統(tǒng)提供的類的分類中,定義新的屬性可以使用的方法匕积,
-(void)setName:(NSString *)name{
objc_setAssociatedObject(<#id object#>, <#const void *key#>, <#id value#>, <#objc_AssociationPolicy policy#>)
}
-(NSString *)name{
objc_getAssociatedObject(<#id object#>, <#const void *key#>)
}
理解objc_msgSend的作用
Objective-C是基于運(yùn)行時(shí)的語言盈罐,在調(diào)用[]方法時(shí)會(huì)轉(zhuǎn)換成
objc_msgSend(<#id self#>, <#SEL op, ...#>,...)
該函數(shù)是參數(shù)可變的,主動(dòng)調(diào)用需要引入#import <objc/message.h>頭文件
例如:
- (void)viewDidLoad {
[super viewDidLoad];
objc_msgSend(self,@selector(haha)); // 打印haha
}
-(void)haha{
NSLog(@"haha");
}
理解消息轉(zhuǎn)發(fā)機(jī)制
iOS消息轉(zhuǎn)發(fā)分為三個(gè)步驟闪唆,第一步先查找是否動(dòng)態(tài)添加了該方法盅粪,如果沒有則進(jìn)行第二步,查找備源接受者苞氮,如果沒有執(zhí)行第三步湾揽,封裝查找不到的方法,直接把消息發(fā)送給目標(biāo)對(duì)象笼吟。
用“方法調(diào)配”技術(shù)調(diào)配“黑盒方法”
iOS中消息列表的緩存是一個(gè)類似于字典的類型库物,會(huì)根據(jù)SEL映射IMP的地址,那么就可以通過交換映射地址的方法來實(shí)現(xiàn)變更系統(tǒng)自帶API的功能贷帮。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
Method m1 = class_getInstanceMethod([self class], @selector(haha));
Method m2 = class_getInstanceMethod([self class], @selector(hehe));
method_exchangeImplementations(m1, m2);
[self hehe]; //打印haha
}
-(void)hehe{
NSLog(@"hehe");
}
-(void)haha{
NSLog(@"haha");
}
使用方法調(diào)配技術(shù)需要的注意點(diǎn)就是方法內(nèi)調(diào)用被交換的方法后悔死循環(huán)
理解“類對(duì)象”的用意
類和對(duì)象的經(jīng)典的繼承關(guān)系圖
注意點(diǎn)是盡量使用==在判斷類對(duì)象的類型是否相等戚揭,不要使用isEqual。