從objc-中國(guó)摘抄

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?幾種消息傳遞機(jī)制

? ? ? ?首先我們來(lái)看看每種機(jī)制的具體特點(diǎn)羊精。在這個(gè)基礎(chǔ)上裆悄,下一節(jié)我們會(huì)畫一個(gè)流程圖來(lái)幫我們?cè)诰唧w情況下正確選擇應(yīng)該使用的機(jī)制嘉抓。最后始绍,我們會(huì)介紹一些蘋果框架里的例子并且解釋為什么在那些用例中會(huì)選擇這樣的機(jī)制访锻。

#KVO

KVO 是提供對(duì)象屬性被改變時(shí)的通知的機(jī)制。KVO 的實(shí)現(xiàn)在 Foundation 中屁置,很多基于 Foundation 的框架都依賴它焊夸。想要了解更多有關(guān) KVO 的最佳實(shí)踐仁连,請(qǐng)閱讀本期 Daniel 寫的 KVO 和 KVC 文章蓝角。

如果只對(duì)某個(gè)對(duì)象的值的改變感興趣的話阱穗,就可以使用 KVO 消息傳遞。不過(guò)有一些前提:第一使鹅,接收者(接收對(duì)象改變的通知的對(duì)象)需要知道發(fā)送者 (值會(huì)改變的對(duì)象)揪阶;第二,接收者需要知道發(fā)送者的生命周期患朱,因?yàn)樗枰诎l(fā)送者被銷毀前注銷觀察者身份鲁僚。如果這兩個(gè)要去符合的話,這個(gè)消息傳遞機(jī)制可以一對(duì)多(多個(gè)觀察者可以注冊(cè)觀察同一個(gè)對(duì)象的變化)

如果要在 Core Data 上使用 KVO 的話裁厅,方法會(huì)有些許差別冰沙。這和 Core Data 的惰性加載 (faulting) 機(jī)制有關(guān)。一旦一個(gè) managed object 被惰性加載處理的話执虹,即使它的屬性沒(méi)有被改變拓挥,它還是會(huì)觸發(fā)相應(yīng)的觀察者。

通知

要在代碼中的兩個(gè)不相關(guān)的模塊中傳遞消息時(shí)袋励,通知機(jī)制是非常好的工具侥啤。通知機(jī)制廣播消息,當(dāng)消息內(nèi)容豐富而且無(wú)需指望接收者一定要關(guān)注的話這一招特別有用茬故。

通知可以用來(lái)發(fā)送任意消息盖灸,甚至可以包含一個(gè) userInfo 字典。你也可以繼承 NSNotification 寫一個(gè)自己的通知類來(lái)自定義行為磺芭。通知的獨(dú)特之處在于赁炎,發(fā)送者和接收者不需要相互知道對(duì)方,所以通知可以被用來(lái)在不同的相隔很遠(yuǎn)的模塊之間傳遞消息钾腺。這就意味著這種消息傳遞是單向的甘邀,我們不能回復(fù)一個(gè)通知。

委托 (Delegation)

Delegation 在蘋果的框架中廣泛存在垮庐。它讓我們能自定義對(duì)象的行為松邪,并收到一些觸發(fā)的事件。要使用 delegation 模式的話哨查,發(fā)送者需要知道接收者逗抑,但是反過(guò)來(lái)沒(méi)有要求。因?yàn)榘l(fā)送者只需要知道接收者符合一定的協(xié)議寒亥,所以它們兩者結(jié)合的很松邮府。

因?yàn)?delegate 協(xié)議可以定義任何的方法,我們可以照著自己的需求來(lái)傳遞消息溉奕」涌可以用方法參數(shù)來(lái)傳遞消息內(nèi)容,delegate 可以通過(guò)返回值的形式來(lái)給發(fā)送者作出回應(yīng)加勤。如果只要在相對(duì)接近的兩個(gè)模塊間傳遞消息仙辟,delgation 是很靈活很直接的消息傳遞機(jī)制同波。

過(guò)度使用 delegation 也會(huì)帶來(lái)風(fēng)險(xiǎn)。如果兩個(gè)對(duì)象結(jié)合得很緊密叠国,任何其中一個(gè)對(duì)象都不能單獨(dú)運(yùn)轉(zhuǎn)未檩,那么就不需要用 delegate 協(xié)議了。這些情況下粟焊,對(duì)象已經(jīng)知道各自的類型冤狡,可以直接交流。兩個(gè)比較新的例子是 UICollectionViewLayout 和 NSURLSessionConfiguration项棠。

Block

Block 是最近才加入 Objective-C 的悲雳,首次出現(xiàn)在 OS X 10.6 和 iOS 4 平臺(tái)上。Block 通诚阕罚可以完全替代 delegation 消息傳遞機(jī)制的角色怜奖。不過(guò)這兩種機(jī)制都有它們自己的獨(dú)特需求和優(yōu)勢(shì)。

一個(gè)不使用 block 的理由通常是 block 會(huì)存在導(dǎo)致 retain 環(huán) (retain cycles) 的風(fēng)險(xiǎn)翅阵。如果發(fā)送者需要 retain block 但又不能確保引用在什么時(shí)候被賦值為 nil歪玲, 那么所有在 block 內(nèi)對(duì) self 的引用就會(huì)發(fā)生潛在的 retain 環(huán)。

假設(shè)我們要實(shí)現(xiàn)一個(gè)用 block 回調(diào)而不是 delegate 機(jī)制的 table view 里的選擇方法掷匠,如下所示:

self.myTableView.selectionHandler = ^void(NSIndexPath *selectedIndexPath) {

// 處理選擇

};

這兒的問(wèn)題是滥崩,self 會(huì) retain table view,table view 為了讓 block 之后可以使用而又需要 retain 這個(gè) block讹语。然而 table view 不能把這個(gè)引用設(shè)為 nil钙皮,因?yàn)樗恢朗裁磿r(shí)候不需要這個(gè) block 了。如果我們不能保證打破 retain 環(huán)并且我們需要 retain 發(fā)送者顽决,那么 block 就不是一個(gè)的好選擇短条。

NSOperation 是使用 block 的一個(gè)好范例。因?yàn)樗谝欢ǖ牡胤酱蚱屏?retain 環(huán)才菠,解決了上述的問(wèn)題茸时。


self.queue = [[NSOperationQueue alloc] init];

MyOperation *operation = [[MyOperation alloc] init];

operation.completionBlock = ^{

[self finishedOperation];

};

[self.queue addOperation:operation];

一眼看來(lái)好像上面的代碼有一個(gè) retain 環(huán):self retain 了 queue,queue retain 了 operation赋访, operation retain 了 completionBlock可都, 而 completionBlock retain 了 self。然而蚓耽,把 operation 加入 queue 中會(huì)使 operation 在某個(gè)時(shí)間被執(zhí)行渠牲,然后被從 queue 中移除。(如果沒(méi)被執(zhí)行步悠,問(wèn)題就大了签杈。)一旦 queue 把 operation 移除,retain 環(huán)就被打破了鼎兽。

另一個(gè)例子是:我們?cè)趯懸粋€(gè)視頻編碼器的類答姥,在類里面我們會(huì)調(diào)用一個(gè) encodeWithCompletionHandler: 的方法铣除。為了不出問(wèn)題,我們需要保證編碼器對(duì)象在某個(gè)時(shí)間點(diǎn)會(huì)釋放對(duì) block 的引用踢涌。其代碼如下所示

@interface Encoder ()

@property (nonatomic, copy) void (^completionHandler)();

@end

@implementation Encoder

- (void)encodeWithCompletionHandler:(void (^)())handler

{

self.completionHandler = handler;

// 進(jìn)行異步處理...

}

// 這個(gè)方法會(huì)在完成后被調(diào)用一次

- (void)finishedEncoding

{

self.completionHandler();

self.completionHandler = nil; // <- 不要忘了這個(gè)!

}

@end

一旦任務(wù)完成,completion block 調(diào)用過(guò)了以后序宦,我們就應(yīng)該把它設(shè)為 nil睁壁。

如果一個(gè)被調(diào)用的方法需要發(fā)送一個(gè)一次性的消息作為回復(fù),那么使用 block 是很好的選擇互捌, 因?yàn)檫@樣做我們可以打破潛在的 retain 環(huán)潘明。另外,如果將處理的消息和對(duì)消息的調(diào)用放在一起可以增強(qiáng)可讀性的話秕噪,我們也很難拒絕使用 block 來(lái)進(jìn)行處理钳降。在用例之中,使用 block 來(lái)做完成的回調(diào)腌巾,錯(cuò)誤的回調(diào)遂填,或者類似的事情,是很常見(jiàn)的情況澈蝙。

? ? ? ? ? ? ? ? ? ? ? ? ? ?Target-Action


Target-Action 是回應(yīng) UI 事件時(shí)典型的消息傳遞方式吓坚。iOS 上的 UIControl 和 Mac 上的 NSControl/NSCell 都支持這個(gè)機(jī)制。Target-Action 在消息的發(fā)送者和接收者之間建立了一個(gè)松散的關(guān)系灯荧。消息的接收者不知道發(fā)送者礁击,甚至消息的發(fā)送者也不知道消息的接收者會(huì)是什么。如果 target 是 nil逗载,action 會(huì)在響應(yīng)鏈 (responder chain) 中被傳遞下去哆窿,直到找到一個(gè)響應(yīng)它的對(duì)象。在 iOS 中厉斟,每個(gè)控件甚至可以和多個(gè) target-action 關(guān)聯(lián)挚躯。

基于 target-action 傳遞機(jī)制的一個(gè)局限是,發(fā)送的消息不能攜帶自定義的信息擦秽。在 Mac 平臺(tái)上 action 方法的第一個(gè)參數(shù)永遠(yuǎn)接收者秧均。iOS 中,可以選擇性的把發(fā)送者和觸發(fā) action 的事件作為參數(shù)号涯。除此之外就沒(méi)有別的控制 action 消息內(nèi)容的方法了目胡。

? ? ? ?


? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 做出正確的選擇

基于上述對(duì)不同消息傳遞機(jī)制的特點(diǎn),我們畫了一個(gè)流程圖來(lái)幫助我們?cè)诓煌榫诚伦龀霾煌倪x擇链快。一句忠告:流程圖的建議不代表最終答案誉己。有些時(shí)候別的選擇依然能達(dá)到應(yīng)有的效果。只不過(guò)大多數(shù)情況下這張圖能引導(dǎo)你做出正確的決定域蜗。

Decision flow chart for communication patterns in Cocoa

圖中有些細(xì)節(jié)值得深究:

有個(gè)框中說(shuō)到: 發(fā)送者支持 KVO巨双。這不僅僅是說(shuō)發(fā)送者會(huì)在值改變的時(shí)候發(fā)送 KVO 通知噪猾,而且說(shuō)明觀察者需要知道發(fā)送者的生命周期。如果發(fā)送者被存在一個(gè) weak 屬性中筑累,那么發(fā)送者有可能會(huì)自己變成 nil袱蜡,那時(shí)觀察者會(huì)導(dǎo)致內(nèi)存泄露。

一個(gè)在最后一行的框里說(shuō)慢宗,消息直接響應(yīng)方法調(diào)用坪蚁。也就是說(shuō)方法調(diào)用的接收者需要給調(diào)用者一個(gè)消息作為方法調(diào)用的直接反饋。這也就是說(shuō)處理消息的代碼和調(diào)用方法的代碼必須在同一個(gè)地方镜沽。

最后在右下角的地方敏晤,一個(gè)選擇分支這樣說(shuō):發(fā)送者能確保釋放對(duì) block 的引用嗎?這涉及到了我們之前討論 block 的 API 存在潛在的 retain 環(huán)的問(wèn)題缅茉。如果發(fā)送者不能保證在某個(gè)時(shí)間點(diǎn)會(huì)釋放對(duì) block 的引用嘴脾,那么你會(huì)惹上 retain 環(huán)的麻煩。

Framework 示例

本節(jié)我們通過(guò)一些蘋果框架里的例子來(lái)驗(yàn)證流程圖的選擇是否有道理蔬墩,同時(shí)解釋為什么蘋果會(huì)選擇用這些機(jī)制译打。

? ? ? ? ? ? ? ? ? ? ? ? ? KVO

NSOperationQueue 用了 KVO 觀察隊(duì)列中的 operation 狀態(tài)屬性的改變情況 (isFinished,isExecuting拇颅,isCancelled)扶平。當(dāng)狀態(tài)改變的時(shí)候,隊(duì)列會(huì)收到 KVO 通知蔬蕊。為什么 operation 隊(duì)列要用 KVO 呢结澄?

消息的接收者(operation 隊(duì)列)知道消息的發(fā)送者(operation),并 retain 它并控制后者的生命周期岸夯。另外麻献,在這種情況下只需要單向的消息傳遞機(jī)制。當(dāng)然如果考慮到 oepration 隊(duì)列只關(guān)心那些改變 operation 的值的改變情況的話猜扮,就還不足以說(shuō)服大家使用 KVO 了勉吻。但我們可以這么理解:被傳遞的消息可以被當(dāng)成值的改變來(lái)處理。因?yàn)?state 屬性在 operation 隊(duì)列以外也是有用的旅赢,所以這里適合用 KVO齿桃。


當(dāng)然 KVO 不是唯一的選擇。我們也可以將 operation 隊(duì)列作為 operation 的 delegate 來(lái)使用煮盼,operation 會(huì)調(diào)用類似 operationDidFinish: 或者 operationDidBeginExecuting: 等方法把它的 state 傳遞給 queue短纵。這樣就不太方便了,因?yàn)?operation 要保存 state 屬性僵控,以便于調(diào)用這些 delegate 方法香到。另外,由于 queue 不能主動(dòng)獲取 state 信息,所以 queue 也必須保存所有 operation 的 state悠就。

Notifications

Core Data 使用 notification 傳遞事件(例如一個(gè) managed object context 中的改變————NSManagedObjectContextObjectsDidChangeNotification)

發(fā)生改變時(shí)觸發(fā)的 notification 是由 managed object contexts 發(fā)出的千绪,所以我們不能假定消息的接收者知道消息的發(fā)送者。因?yàn)橄⒌脑搭^不是一個(gè) UI 事件梗脾,很多接收者可能在關(guān)注著此消息荸型,并且消息傳遞是單向的,所以 notification 是唯一可行的選擇炸茧。

Delegation

Table view 的 delegate 有多重功能瑞妇,它可以從管理 accessory view,直到追蹤在屏幕上顯示的 cell宇立。例如我們可以看看 tableView:didSelectRowAtIndexPath: 方法踪宠。為什么用 delegate 實(shí)現(xiàn)而不是 target-action 機(jī)制自赔?

正如我們?cè)谏鲜隽鞒虉D中看到的妈嘹,用 target-action 時(shí),不能傳遞自定義的數(shù)據(jù)绍妨。而選中 table view 的某個(gè) cell 時(shí)润脸,collection view 不僅需要告訴我們一個(gè) cell 被選中了,也要通過(guò) index path 告訴我們哪個(gè) cell 被選中了他去。如果我們照著這個(gè)思路毙驯,流程圖會(huì)引導(dǎo)我們使用 delegation 機(jī)制。


如果不在消息傳遞中包含選中 cell 的 index path灾测,而是讓選中項(xiàng)改變時(shí)我們像 table view 主動(dòng)詢問(wèn)并獲取選中 cell 的相關(guān)信息爆价,會(huì)怎樣呢?這會(huì)非常不方便媳搪,因?yàn)槲覀儽仨氂涀‘?dāng)前選中項(xiàng)的數(shù)據(jù)铭段,這樣才能在多選擇中知道哪些 cell 是被新選中的。

同理秦爆,我們可以想象通過(guò)觀察 table view 選中項(xiàng)的 index path 屬性序愚,當(dāng)該值發(fā)生改變的時(shí)候,獲得一個(gè)選中項(xiàng)改變的通知等限。不過(guò)我們會(huì)遇到上述相似問(wèn)題:不做記錄的話我們就不能分辨哪一個(gè) cell 被選擇或取消選擇了爸吮。

Block

我們用 -[NSURLSession dataTaskWithURL:completionHandler:] 來(lái)作為一個(gè) block API 的介紹。那么從 URL 加載部分返回給調(diào)用者是怎么傳遞消息的呢望门?首先形娇,作為 API 的調(diào)用者,我們知道消息的發(fā)送者筹误,但是我們并沒(méi)有 retain 它埂软。另外,這是個(gè)單向的消息傳遞————它直接調(diào)用 dataTaskWithURL: 的方法。如果我們對(duì)照流程圖勘畔,會(huì)發(fā)現(xiàn)這屬于 block 消息傳遞機(jī)制所灸。



有其他的選項(xiàng)嗎?當(dāng)然炫七,蘋果自己的 NSURLConnection 就是最好的例子爬立。NSURLConnection在 block 問(wèn)世之前就存在了,所以它并沒(méi)有用 block 來(lái)實(shí)現(xiàn)消息傳遞万哪,而是使用 delegation 來(lái)完成侠驯。當(dāng) block 出現(xiàn)以后,蘋果就在 OS X 10.7 和 iOS 5 平臺(tái)上的 NSURLConnection 中加了 sendAsynchronousRequest:queue:completionHandler:奕巍,所以我們不再在簡(jiǎn)單的任務(wù)中使用 delegate 了吟策。

因?yàn)?NSURLSession 是個(gè)最近在 OS X 10.9 和 iOS 7 才出現(xiàn)的 API,所以它們使用 block 來(lái)實(shí)現(xiàn)消息傳遞機(jī)制(NSURLSession 有一個(gè) delegate的止,但是是用于其他目的)檩坚。

Target-Action

一個(gè)明顯的 target-action 用例是按鈕。按鈕在不被按下的時(shí)候不需要發(fā)送任何的信息诅福。為了這個(gè)目的匾委,target-action 是 UI 中消息傳遞的最佳選擇。


如果 target 是明確指定的氓润,那么 action 消息會(huì)發(fā)送給指定的對(duì)象赂乐。如果 target 是 nil, action 消息會(huì)一直在響應(yīng)鏈中被傳遞下去咖气,直到找到一個(gè)能處理它的對(duì)象挨措。在這種情況下,我們有一個(gè)完全解耦的消息傳遞機(jī)制:發(fā)送者不需要知道接收者崩溪,反之亦然浅役。

Target-action 機(jī)制非常適合響應(yīng) UI 的事件。沒(méi)有其他的消息傳遞機(jī)制能夠提供相同的功能悯舟。雖然 notification 在發(fā)送者和接收者的松散關(guān)系上最接近它担租,但是 target-action 可以用于響應(yīng)鏈——只有一個(gè)對(duì)象獲得 action 并響應(yīng),action 在響應(yīng)鏈中傳遞抵怎,直到能遇到響應(yīng)這個(gè) action 的對(duì)象奋救。


? ? ? ? ? ? ? ? 總結(jié)

一開(kāi)始接觸這么多的消息傳遞機(jī)制的時(shí)候,我們可能有些無(wú)所適從反惕,覺(jué)得所有的機(jī)制都可以被選用尝艘。不過(guò)一旦我們仔細(xì)分析每個(gè)機(jī)制的時(shí)候,它們各自都有特殊的要求和能力姿染。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末背亥,一起剝皮案震驚了整個(gè)濱河市秒际,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌狡汉,老刑警劉巖娄徊,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異盾戴,居然都是意外死亡寄锐,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門尖啡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)橄仆,“玉大人,你說(shuō)我怎么就攤上這事衅斩∨韫耍” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵畏梆,是天一觀的道長(zhǎng)您宪。 經(jīng)常有香客問(wèn)我,道長(zhǎng)具温,這世上最難降的妖魔是什么蚕涤? 我笑而不...
    開(kāi)封第一講書人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任筐赔,我火速辦了婚禮铣猩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘茴丰。我一直安慰自己达皿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布贿肩。 她就那樣靜靜地躺著峦椰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪汰规。 梳的紋絲不亂的頭發(fā)上汤功,一...
    開(kāi)封第一講書人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音溜哮,去河邊找鬼滔金。 笑死,一個(gè)胖子當(dāng)著我的面吹牛茂嗓,可吹牛的內(nèi)容都是我干的餐茵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼述吸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼忿族!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤道批,失蹤者是張志新(化名)和其女友劉穎错英,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體隆豹,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡走趋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了噪伊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片簿煌。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鉴吹,靈堂內(nèi)的尸體忽然破棺而出姨伟,到底是詐尸還是另有隱情,我是刑警寧澤豆励,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布夺荒,位于F島的核電站,受9級(jí)特大地震影響良蒸,放射性物質(zhì)發(fā)生泄漏技扼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一嫩痰、第九天 我趴在偏房一處隱蔽的房頂上張望剿吻。 院中可真熱鬧,春花似錦串纺、人聲如沸丽旅。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)榄笙。三九已至,卻和暖如春祷蝌,著一層夾襖步出監(jiān)牢的瞬間茅撞,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工巨朦, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留米丘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓罪郊,卻偏偏與公主長(zhǎng)得像蠕蚜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子悔橄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

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

  • 每個(gè)應(yīng)用或多或少都由一些需要相互傳遞消息的對(duì)象結(jié)合起來(lái)以完成任務(wù)靶累。在這篇文章里腺毫,我們將介紹所有可用的消息傳遞機(jī)制,...
    愛(ài)敲代碼的果果閱讀 3,969評(píng)論 0 2
  • 每個(gè)應(yīng)用程序或多或少挣柬,都由一些松耦合的對(duì)象構(gòu)成潮酒,這些對(duì)象彼此之間要想很好的完成任務(wù),就需要進(jìn)行消息傳遞邪蛔。 本文將介...
    石丘閱讀 1,719評(píng)論 4 7
  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,139評(píng)論 30 470
  • 介紹: KVO -- 值改變 + 兩要求 當(dāng)對(duì)象中的某個(gè)屬性值發(fā)生了改變故源,可以對(duì)這些值的觀察者做出通知。 有兩個(gè)要...
    錢噓噓閱讀 1,127評(píng)論 0 9
  • 若云:爸爸要拋棄你們汞贸,去找男朋友了绳军。 佳佳:不要嘛,若云~ 晨晨:去找吧矢腻,支持你门驾,順便看他室友帥不,好看的話多柑,給我...
    高平調(diào)閱讀 108評(píng)論 0 0