观察员、通知、代表swift ios8
我正在寻找一些建议,比如如何最好地实现一些东西,我认为可能是一个观察者,可能是一个多播委托,或者可能我只是使用notification enter 我正在创建一个连接到各种数据源并生成通用数据格式的观察员、通知、代表swift ios8,ios,swift,design-patterns,delegates,notifications,Ios,Swift,Design Patterns,Delegates,Notifications,我正在寻找一些建议,比如如何最好地实现一些东西,我认为可能是一个观察者,可能是一个多播委托,或者可能我只是使用notification enter 我正在创建一个连接到各种数据源并生成通用数据格式的DataManager类 例子: 我们可以从内部核心位置、文件播放、网络套接字提供的位置等生成位置消息 返回的数据类型是具有通用格式的LocationMessage,如有必要,还可以将其转换为CLLocation 在我当前的“多代理”模型中,如果你想获得位置更新,你必须实现LocationConsum
DataManager
类
例子:
我们可以从内部核心位置、文件播放、网络套接字提供的位置等生成位置消息
返回的数据类型是具有通用格式的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
的简单性在通知中丢失。我想我必须为我关心的每个通知专门注册-对吗
我不能这样做:
class notificaitonClass : LocationNotifiee, WeatherNotifiee {
}
所以我想我的问题是
- 1:我是否实现了观察者模式
- 2:我目前的方法有哪些缺点
- 3:有没有办法定义一个swift协议,使实现它的类自动订阅一组通知
- 4:什么是更好的方法
(希望这不是太模糊)Stackoverflow不是回答这个问题的最佳论坛,你应该试试。但见鬼,这是我的快速答案 不要称之为委托 在目标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 {
…
}
}
我同意杰弗里托马斯的观点。您所做的是完全正确的,但是Swift和Objective-C都没有将多播委托的概念作为标准设计模式 这并不是说它有什么问题。拥有一个符合给定协议的对象数组是完全有效的,就像使用map函数调用该数组中所有对象的闭包一样。瞧,即时多播代理 Cocoa/Cocoa Touch程序员(像我一样)如果使用该术语,会觉得你很滑稽,因为术语“委托”在Cocoa中的含义相当狭窄,而该含义不包括多播委托 在我看来,您的多播代理的设计已经非常“规划”(双关语)了,所以如果这很适合您需要做的事情,那么就去做吧。您并没有打破委托设计模式——您正在实现一种不同的设计模式,这种模式在平台上并没有广泛使用,但却是完全有效和有用的 当我第一次开始阅读你的问题时,我认为“代理是一对一的。通知更合适。”这是因为,作为一名典型的Cocoa/Cocoa Touch开发者,“代理”一词对我的含义很狭隘,不包括多播代理。然而,在我用谷歌搜索这个术语之前,我很清楚你的意思,我想的是符合通用协议和映射函数的对象数组 通知是解决此问题的另一种完全有效的方法。我觉得通知和多播代理之间的区别在于谁来做这项工作。在多播代理中,发送方必须维护一个目标列表(我不太愿意称它们为代理),并向每个目标发送所需的消息 在通知中,发送者不知道或不关心谁在听。发送者只是发出一个信号弹,听者的责任在于关心和回应。KVO在这方面与通知类似 编辑: 再想一想,我认为map函数不是正确的选择。Map用于获取一个源数组,对每个元素执行一些变异操作,并在新数组中返回变异的元素。它会创建一个新数组,您可以忽略它 对于多播代理设计模式,不需要将源数组转换(映射)为目标数组。您需要让数组中的每个元素执行一项任务 最好使用forEach方法。这条线
locationDelegates.map(closure)
将改为如下所示:
locationDelegates.foreach
{
closure()
}
(我想我有那个语法