繁体   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