簡體   English   中英

觀察者,通知,代表swift ios8

[英]Observer, Notification, Delegate swift ios8

我正在尋找一些建議,以最好地實現我認為可能是觀察者,可能是多播委托的東西,或者也許我將僅使用通知輸入。

我正在創建一個DataManager類,該類連接到各種數據源並產生一種通用的數據格式。

例:

我們可以從內部核心位置文件播放網絡套接字提供的位置等生成LocationMessage

返回的數據類型是具有通用格式的LocationMessage ,如有必要,也可以將其轉換為CLLocation

在我當前的“多委托”模型中,如果要獲取位置更新,則必須實現LocationConsumer協議,該協議定義了

func didUpdateLocation(newLocation: LocationMessage) 
{
    println("\(__FUNCTION__)   \(newLocation)")
}

那你會

//Instantiate a data manager
let dm : DataManager = DataManager()

//Register yourself as a delegate
dm.addLocationDelegate(self)

在內部,當我們獲得新的位置數據時,將稱為:

    let closure = {
        (delegate : LocationDataConsumer) -> () in
        dispatch_async(self.delegateQueue) {
            delegate.didUpdateLocation(parsedLocation)
        }
    }
    locationDelegates.map(closure)

其中locationDelegates[LocationConsumer]的數組

討論

因此,首先,這顯然並不真正遵循委托模式,因為您不應擁有多個委托。

但是,我真正喜歡當前方法的地方是,使用協議似乎很干凈,以便將類標識為關心特定數據類型。 但是,我不滿意的是“打破”了標准的委托模式。

通過閱讀,我認為最合適的方法是使用“ 通知模式”,但是,從編碼的角度來看,我認為涉及到更多的維護工作(盡管我可能是錯的)。 使用此委托方法僅實現協議並調用addDelegate的簡單性在Notifications中丟失了。 我認為我必須為我關心的每個通知都專門注冊-對嗎?

我無法執行以下操作:

class notificaitonClass : LocationNotifiee, WeatherNotifiee {

}

所以我想我的問題是

  • 1:我是否實現了觀察者模式
  • 2:我目前的做法有哪些弊端
  • 3:有沒有一種方法可以定義一個快速協議,該協議將使實現該協議的類自動訂閱一組通知
  • 4:哪種方法更好?

(希望這不太模糊)

Stackoverflow並不是回答這個問題的最佳論壇,您應該嘗試developers.stackexchange.com 但到底,這是我的快速答案。

不要稱其為代表

在Objective C / Swift中,委托具有特定含義,您描述的模式不合適。 將其稱為事件處理程序,將其稱為更改回調,將其稱為多重委托(ala dm.addLocationMultiDelegate(self) ):只是不要通過重載術語“委托”來使人們感到困惑。

重新考慮通知

您可以控制什么是通知以及何時發送。 您可能有一個DataMangerDidUpdateLocationNotification ,可以將其從任何來源發布到任何接收者。 如果需要跟蹤誰發布了通知,則可以在userInfo中使用DataMangerSourceKey

此外,您可以將其進一步推廣。 您可能具有一組數據管理器更改的DataMangerDidChangeNotification 您可能需要一個DataMangerChangeTypeKey

例如:

NSNotificationCenter.defaultCenter().addObserverForName(DataMangerDidChangeNotification, object: nil, queue: nil) {
    note in
    let changeType = note.userInfo![DataMangerChangeTypeKey] as String

    if changeType == DataMangerChangeTypeLocation {
        …
    } else if changeType == DataMangerChangeTypeOther {
        …
    }
}

我同意@JefferyThomas。 您所做的工作是完全有效的,但是Swift和Objective-C都沒有將多播委托作為標准設計模式的概念。

這並不是說它有什么問題。 擁有符合給定協議的對象數組是完全有效的,就像使用map函數調用該數組中所有對象的閉包一樣。 Voila,即時多播代表。

如果您使用該術語,那么Cocoa / Cocoa Touch程序員(像我一樣)很容易對您感興趣,這僅僅是因為術語“委托”在Cocoa中的含義很窄,並且該含義並不涵蓋多播委托。

在我看來,您已經為多播代表設計了很多“映射”(雙關語意),因此,如果這很適合您的工作,那就去做吧。 您並沒有破壞委托設計模式-您正在實現的是另一種設計模式,該設計模式並未在平台上廣泛使用,但是仍然十分有效和有用。

當我剛開始閱讀您的問題時,我認為“代表是一對一的。通知更適合。” 這是因為,作為典型的Cocoa / Cocoa Touch開發人員,“委托”一詞對我來說具有狹窄的含義-其中不包括多播委托。 但是,在搜索該術語之前,我已經很確定您的意思了,並且我正在考慮符合通用協議和map函數的對象數組。

通知是解決問題的另一種完全有效的方法。 令我驚訝的是,通知和多播委托之間的區別在於誰來工作。 在多播委托中,發送者必須維護一個目標列表(我會毫不猶豫地稱其為委托),並向每個目標發送所需的消息。

在通知中,發件人不知道或不在乎誰在聽。 發送方只是發出信號彈,而負擔是監聽者需要照顧和響應的負擔。 在這方面,KVO與通知類似。

編輯:

再多考慮一下,我認為map函數不是正確的選擇。 Map旨在獲取一個源數組,對每個元素執行一些變異操作,然后將變異后的元素返回到一個新的數組中。 它創建一個新數組,您將忽略它。

對於您的多播委托設計模式,您不需要將源數組轉換(映射)為目標數組。 您需要讓數組中的每個元素執行一項任務。

最好使用forEach方法。 這條線

locationDelegates.map(closure)

看起來像這樣:

locationDelegates.foreach
{
  closure()
}

(我認為我的語法是正確的-最近我主要在Objective-C中工作,而在Swift中變得生銹。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM