Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/115.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
观察员、通知、代表swift ios8_Ios_Swift_Design Patterns_Delegates_Notifications - Fatal编程技术网

观察员、通知、代表swift ios8

观察员、通知、代表swift ios8,ios,swift,design-patterns,delegates,notifications,Ios,Swift,Design Patterns,Delegates,Notifications,我正在寻找一些建议,比如如何最好地实现一些东西,我认为可能是一个观察者,可能是一个多播委托,或者可能我只是使用notification enter 我正在创建一个连接到各种数据源并生成通用数据格式的DataManager类 例子: 我们可以从内部核心位置、文件播放、网络套接字提供的位置等生成位置消息 返回的数据类型是具有通用格式的LocationMessage,如有必要,还可以将其转换为CLLocation 在我当前的“多代理”模型中,如果你想获得位置更新,你必须实现LocationConsum

我正在寻找一些建议,比如如何最好地实现一些东西,我认为可能是一个观察者,可能是一个多播委托,或者可能我只是使用notification enter

我正在创建一个连接到各种数据源并生成通用数据格式的
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()
}
(我想我有那个语法