[翻譯]通訊模式(Communication Patterns)

Peter_shenlipingUpUp發表於2019-02-21

引言

看到標題的也許有一些老司機看過原文,此文是基於原文翻譯加上自己理解,為了更好的學習iOS~(文章並沒有寫如何運用,主要是探討什麼時候用。)
原文地址:https://www.objc.io/issues/7-foundation/communication-patterns/

我們在開發過程中,常用的兩個物件之間的相互通訊的方式有很五種

  • Target-Action
  • Delegation
  • block
  • KVO
  • Notifications
    本文是討論各個通訊的使用,以及在什麼時候用這些通訊方式。在通訊的過程中,往往一個是接收者,一個是傳送者。
Target-Action

這個方式相信大家見的就很多了,在寫Button或者手勢的時候,都會用到addTagert這個方法。Target-Action是用於在使用者介面事件響應中傳送訊息的典型模式,一般是用於處理動作訊息。他包含了 兩個資料,一個是選擇子(selector),還有一個是接收人(target)。在iOS中,能觸發Target-Action事件的一般是基於UIControl的(官方文件說是可以任何物件,不過基本上都是繼承與UIControl的)。一般的Target-Action的接收事件如下:

-  (void)dosomething:(id)sender;
複製程式碼

在Target-Action中,訊息的接收者其實並不知道傳送者是誰,傳送者也不知道訊息的接送者是誰。所以當target是nil的時候,會通過響應者鏈找到某一個接收者去響應這個訊息。這個方式的缺點就是傳遞訊息的時候不能帶著自定義的引數。

Delegation

Delegation在蘋果自己的FrameWorks裡就經常使用,比如我們經常用的 tableViewdelegatedataSource。它允許我們去自定義某一個物件的行為,也可以(被)告訴我們這個物件發生了什麼。在這個通訊過程中,訊息的傳送者需要知道訊息的接收者,也就是這個delegate。我們在用UITableView的時候往往會寫tableView.delegate = self,就是讓tableView這個訊息的傳送者知道訊息的接收者是誰(self)。這樣的耦合度會很低,大家應該都深有體會吧,哈哈哈,有時候可能會找不到這個方法在哪兒。。。
delegate protocol可以定義任何方法,所以你也可以用這些方法傳遞你想要傳遞的引數,而且delegate protocol可以響應這些方法返回的引數。可見delegate protocol的通訊方式是非常的靈活和直接。

block

block也叫閉包函式,講道理的說,只要是Delegation通訊模式下可以做的事情,都可以用block代替。相對來說,block對於程式碼的整體性體驗較好,不會散落在各地。但是blokc會造成迴圈引用,也可能會提前釋放。總之block應用起來,總是對新手那麼的不友好。
block的能夠抓取當前上下文的命名域,怎麼說呢,就是你不需要知道這個具體是什麼東西,裡面是怎麼樣的,你可以直接更具他給的引數或者直接寫你想要寫的程式碼。

#####KVO
KVO是一種通知物件的屬性發生改變的機制。KVO是一種靈活的方式去監聽當前物件屬性的改變,尤其是對於系統屬性的監聽,比如說UITableViewContentOffSet這個值改變的監聽,可以幫我們實現一些比較酷炫的UI效果(你懂的)。
KVO的使用,需要一些必要的條件,比如說你的物件要支援Key-Value Observing機制。而且你要知道這個物件的生命週期,在你不需要的時候移除這個KVO觀察。

Notifications

Notifications這通訊方式,就是一種很好的,系統給我們封裝好的,一對多的廣播。他最大的優勢就是可以跨越層級,對程式碼架構的解耦很有幫助。(現在好像不能說一對多是他的優勢了,貌似Swift裡有多Delegate)
iOS系統在應用過程中會發很多通知,比如說UIKeyboardWillShowNotificationUITextViewTextDidChangeNotification等等各種。
NotificationsKVO一樣,需要知道接收者的生命週期,在最後生命週期結束的時候登出這個NotificationsiOS大部分的生命週期結束的時候都會呼叫- (void)dealloc。所以其實用起來也比較簡單。(當然你要是發生迴圈引用導致當前物件不能釋放,那就沒辦法了(⊙﹏⊙)b)。

討論

對比了這五種方式,那我們什麼時候用呢。上面文章的作者給了這麼一張圖:

通訊模式.png

我想分享下自己對於通訊模式的看法。因為不會畫圖,畫在紙上的話,字太醜了,就寫文字吧。。。。
1.是否直接進行物件的互動而且不需要引數,比如說手勢,Button這些的 。如果是的話,就用Target-Action
2.是否是多層級的,兩個物件是否有聯絡,如果不是的話,就可以用Notifications
3.既然兩個物件是有聯絡的,當你需要監聽值發生變化的時候,可以使用KVO。(單存值變化,而不是其他動作響應的情況下)
4.我是否需要知道這個物件的具體東西,上下文的具體命名域。如果不需要的話,這個時候使用Block會好一點。比如說我們網路請求時候的回撥各種,只要輸入請求引數,然後寫好回撥。中間發生了什麼,其實你知道不知道,並不影響使用。
5.對於Delegationblock我覺得是大部分情況下是可以互相替換的,因為關於迴圈引用這方面,現在各種WeakSelf,StrongSelf的文章。不過在某些情況,比如說你的訊息傳送者需要用到接收者給的返回值的時候,這個時候用Delegation在設計上來說比Block更好。

End

其實對於通訊模式這種理解,對於整體架構,包括響應式程式設計都有很好的幫助。

相關文章