Effective Object-C 52: 6-14

二味赃、對(duì)象言秸、消息吟秩、運(yùn)行期

6. 理解“屬性”這一概念

  • 使用@property 語法來定義對(duì)象中封裝的數(shù)據(jù)
  • 通過“特質(zhì)” 來制定存儲(chǔ)數(shù)據(jù)所需的正確語義
  • 在設(shè)置屬性所對(duì)應(yīng)的實(shí)例變量時(shí)仆百,一定要遵從該屬性所聲明的語義。
  • 開發(fā)iOS : 使用nonatomic 屬性堵腹。atomic 會(huì)影響性能梢杭。

實(shí)例變量訪問方式: 存取方法(access method)(讀取)+ 獲取方法(getter)(寫入)

定義實(shí)例:編譯器會(huì)把其替換成“偏移量”(offset)== "硬編碼"(hardcode)
編譯器計(jì)算出來的偏移量秸滴,在修改類定義后必須重新編譯武契。
Object-C 的偏移量存儲(chǔ)交給“類對(duì)象來處理”

@property 語法:

"點(diǎn)語法" == "存取方法"

自動(dòng)編寫訪問屬性的方法-> “自動(dòng)合成” autosynthesis

Person* aPerson = [Person new];
aPerson.firstName = @"Bob";//Same as
[aPerson setFirstName:@"Bob"];

NSString* lastName = aPerson.lastName;//Same as
NSString* lastName = [aPerson lastName];

@synthesize :去除生成變量名的下劃線。

@dynamic 阻止自動(dòng)合成方法創(chuàng)建

屬性特質(zhì)

原子性(atomic):某操作具有整體性荡含,系統(tǒng)其他部分無法觀察到其中間的操作步驟咒唆,只能看到操作前和操作結(jié)果。 其他命名:(獲取器释液,設(shè)置器全释,保有)。

OC 默認(rèn)情況下 是“原子的”

讀/寫權(quán)限
1.readwrite :擁有 getter误债、 setter

2.readoly : 僅擁有獲取方法浸船。

內(nèi)存管理語義:
Name 語義
assign “純量類型” (scalar type、CGFloat寝蹈、 NSInterger)
unsafe_unretained == assign 但適用于 ”對(duì)象類型“(object type) “非擁有關(guān)系” 當(dāng)對(duì)象被摧毀時(shí)候李命,屬性值不會(huì)清空。
strong “擁有關(guān)系“ 1.設(shè)置新職時(shí):1.保留新值 2.釋放舊值 3.把新值設(shè)置上去
copy == strong 但是設(shè)置方法不保留新值箫老,而是“拷貝”(copy)封字。
weak “非擁有關(guān)系” 1.不保留新值 2.不釋放舊值。對(duì)象遭到摧毀時(shí)耍鬓,屬性值也會(huì)清空(nil out)阔籽。

7. 在對(duì)象內(nèi)部盡量直接訪問實(shí)例變量

寫法: 直接訪問實(shí)例變量 _屬性名 ; 通過屬性:self.屬性名

  • 對(duì)象內(nèi)部提取牲蜀,應(yīng)該通過直接訪問實(shí)例變量來讀笆制,通過屬性來寫。 <_objc(直接訪問) & self.objc >
  • 在初始化和dealloc方法中涣达,都應(yīng)該直接通過實(shí)例變量來讀寫數(shù)據(jù) <_objc>
  • 惰性初始化配置某份數(shù)據(jù)在辆,需通過屬性來讀寫數(shù)據(jù) <self.objc>

8. 理解“對(duì)象同等性”這一個(gè)概念

  • 檢測(cè)對(duì)象的等同性: 1. isEqual: 2. hash
  • 相同對(duì)象必須具有相同的哈希碼, 但兩個(gè)哈希碼相同的對(duì)象未必相同峭判。
  • 不要盲目逐條檢測(cè)每條屬性开缎, 而是應(yīng)該按具體需求制定檢測(cè)方案。
  • hash 方法: 使用計(jì)算速度快而且哈希碼碰撞低的算法林螃。

9. 以“類族模式” 隱藏實(shí)現(xiàn)細(xì)節(jié)

  • 類族模式可以實(shí)現(xiàn)細(xì)節(jié)隱藏在一套簡(jiǎn)單的公共接口后面奕删。
  • 系統(tǒng)框架中經(jīng)常使用類族
  • 從類族的公共抽象基類中繼承子類時(shí) 要小心,應(yīng)優(yōu)先閱讀開發(fā)文檔疗认。

工廠模式(Factory pattern) :基類實(shí)現(xiàn)一個(gè)”類方法“完残、子類繼承基類 跟根據(jù)“類方法” 實(shí)現(xiàn)類實(shí)例伏钠。

10. 在既有類中使用關(guān)聯(lián)對(duì)象存放自定義數(shù)據(jù)

  • 使用“關(guān)聯(lián)對(duì)象” 機(jī)制把兩個(gè)對(duì)象連接起來
  • 定義關(guān)聯(lián)對(duì)象時(shí)可指派對(duì)象內(nèi)存管理語義 == 屬性
  • 一般情況下不使用“關(guān)聯(lián)對(duì)象”, 只有在其他做法不可行時(shí)使用谨设,因?yàn)檫@種做法通常會(huì)引入難以查找的bug熟掂。

對(duì)象中存放相關(guān)需求:

  1. 一般情況下,從對(duì)象所屬的類中繼承一個(gè)子類扎拣,然后改用這個(gè)子類對(duì)象赴肚。
  2. 無法創(chuàng)建子類對(duì)象的情況下,使用 “關(guān)聯(lián)對(duì)象” (Associated Object)二蓝。

“關(guān)聯(lián)對(duì)象 ”存儲(chǔ)語義:

關(guān)聯(lián)類型 等效的@property屬性
OBJC_ASSOCIATION_ASSIGN assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC nonatomic,retain
OBJC_ASSOCIATION_COPY_NONATOMIC nonatomic,copy
OBJC_ASSOCIATION_RETAIN retain
OBJC_ASSOCIATION_COPY copy

方法:

#import <objc/runtime.h>  

OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);

OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
    OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);

OBJC_EXPORT void objc_removeAssociatedObjects(id object)
    OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);

11. 理解objc_msgSend 的作用

  • 消息構(gòu)成: 接收者誉券、選擇子、參數(shù)刊愚。 給某對(duì)象“發(fā)送消息”(invoke a messge) == 在該對(duì)象上“調(diào)用方法”踊跟。
  • 發(fā)送給某對(duì)象的消息全部有“動(dòng)態(tài)消息派發(fā)系統(tǒng)”(dynamic message despatch system)來處理,該系統(tǒng)會(huì)查處對(duì)應(yīng)的方法鸥诽。

OC商玫、對(duì)象的方法調(diào)用: “傳遞消息” (pass a message)。消息:“名稱”(name)或者 “選擇子”(selecor)牡借,可以接受參數(shù)拳昌,可能有返回值。

C蓖捶、靜態(tài)綁定(static biding)編譯期就決定了運(yùn)行時(shí)所應(yīng)調(diào)用的函數(shù)地回。

sendMsg 操作流程:

  1. 接收著所屬類里搜尋“方法列表”(list of methods)
  2. 找到與之相匹配的方法名就跳轉(zhuǎn)至其實(shí)現(xiàn)代碼
  3. 找不到 沿著集成體系往上查找扁远,直到找到為止俊鱼。
  4. 還是找不到-> 執(zhí)行“消息轉(zhuǎn)發(fā)”(message forwarding);

12. 理解消息轉(zhuǎn)發(fā)機(jī)制

  • 消息轉(zhuǎn)發(fā)機(jī)制觸發(fā):對(duì)象無法響應(yīng)某個(gè)選擇子
  • 1.動(dòng)態(tài)方法解析 -> 2.轉(zhuǎn)交給其他對(duì)象解析 -> 3.完整的消息轉(zhuǎn)發(fā)機(jī)制 [3個(gè)步驟 其中一個(gè)步驟完成就不會(huì)啟動(dòng)下一個(gè)步驟]

消息轉(zhuǎn)發(fā)流程:

MacDown logo
MacDown logo

13. 用“方法調(diào)試技術(shù)” 調(diào)試 “黑盒方法”

  • 運(yùn)行期,可以向類中新增或者替換選擇子所對(duì)應(yīng)的方法實(shí)現(xiàn)
  • 通關(guān) “方法調(diào)試”向原有實(shí)現(xiàn)中添加新的功能畅买。
  • 一般調(diào)試的時(shí)候使用并闲,不宜濫用。

方法調(diào)配(method swizzling):object-c 對(duì)象受到消息后谷羞,只有在運(yùn)行期才能解析帝火。利用這一特性覆寫SEL-IMP 關(guān)系,就能改變這個(gè)類的本身的功能湃缎。

動(dòng)態(tài)消息派發(fā)系統(tǒng) 根據(jù) :類的方法列表會(huì)把選擇子的名稱映射到相關(guān)的實(shí)現(xiàn)上犀填。

IMP: 函數(shù)方法指針。 id (* IMP)(id, SEL, ...)

類的選擇子映射表 圖1:

MacDown logo
MacDown logo

開發(fā)者幾個(gè)開發(fā)方向:1. 新增選擇子 2. 改變選擇子所對(duì)應(yīng)的方法實(shí)現(xiàn) 3. 交換兩個(gè)選擇子所映射到的指針嗓违。

改變后映射表 圖2:


MacDown logo
MacDown logo
交換方法:Void method_exchangeImplementations(Method m1, Method m2)
獲取相關(guān)的方法: Mehod class_getInstanceMethod(Class aClass, SEL aSelector)

Method originalMethod = class_getInstanceMethod([NSString class], @selector(lowercaseString));
Method swappedMethod = class_getInstanceMethod([NSString class], @selector(uppercaseString));
method_exchangeImplementations(originalMethod, swappedMethod);

調(diào)試方案:

  1. 添加一個(gè)分類(category) 一個(gè)新方法
  2. 與現(xiàn)有的方法互換
  3. 可以實(shí)現(xiàn)日志九巡、 適用于短時(shí)間現(xiàn)有版本方法更改問題。

14. 理解“類對(duì)象”的用意

  • 沒個(gè)實(shí)例都有一個(gè)指向Class對(duì)象的指針蹂季,用以表明其類型冕广,這些Class對(duì)象構(gòu)成類的繼承體系疏日。 [Class isa]
  • 使用類型信息查詢方法來探知無法在編譯器確定類型的對(duì)象。
  • 盡量使用類型信息查詢方法來確定對(duì)象類型撒汉,不要直接比較類對(duì)象沟优,因?yàn)槟承?duì)象可能實(shí)現(xiàn)了消息轉(zhuǎn)發(fā)功能。

"isMemberOfCalss:" 判定對(duì)象是否為某個(gè)對(duì)象的實(shí)力

"isKindOfClass:" 對(duì)象是否是這個(gè)類或者其派生類的實(shí)力睬辐。

//判斷對(duì)象是否是某個(gè)類的實(shí)例
if ([objec class] == [EOCSomeClass class]){
    //'objec' is an instance of EOCSomeClass
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末挠阁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子溯饵,更是在濱河造成了極大的恐慌鹃唯,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓣喊,死亡現(xiàn)場(chǎng)離奇詭異坡慌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)藻三,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門洪橘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人棵帽,你說我怎么就攤上這事熄求。” “怎么了逗概?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵弟晚,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我逾苫,道長(zhǎng)卿城,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任铅搓,我火速辦了婚禮瑟押,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘星掰。我一直安慰自己多望,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布氢烘。 她就那樣靜靜地躺著怀偷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪播玖。 梳的紋絲不亂的頭發(fā)上椎工,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼晋渺。 笑死镰绎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的木西。 我是一名探鬼主播畴栖,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼八千!你這毒婦竟也來了吗讶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤恋捆,失蹤者是張志新(化名)和其女友劉穎照皆,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沸停,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膜毁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了愤钾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘟滨。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖能颁,靈堂內(nèi)的尸體忽然破棺而出杂瘸,到底是詐尸還是另有隱情,我是刑警寧澤伙菊,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布败玉,位于F島的核電站,受9級(jí)特大地震影響镜硕,放射性物質(zhì)發(fā)生泄漏运翼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一谦疾、第九天 我趴在偏房一處隱蔽的房頂上張望南蹂。 院中可真熱鬧,春花似錦念恍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至该默,卻和暖如春瞳氓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背栓袖。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來泰國打工匣摘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留店诗,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓音榜,卻偏偏與公主長(zhǎng)得像庞瘸,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赠叼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容