Effective Objective-C 2.0筆記(二)

對(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ì)象。

1.png

用“方法調(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)系圖

2.png

注意點(diǎn)是盡量使用==在判斷類對(duì)象的類型是否相等,不要使用isEqual。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容