我应该在 Swift 中使用单例位置管理器吗?
Posted
技术标签:
【中文标题】我应该在 Swift 中使用单例位置管理器吗?【英文标题】:Should I use a singleton location manager in Swift? 【发布时间】:2019-06-12 20:43:18 【问题描述】:上下文:
我的应用需要用户在几个不相关的视图控制器中的当前位置,到目前为止,我正在每个控制器中创建一个 CLLocationManager 并一遍又一遍地请求当前位置。
但是,我觉得它不合适。这是重复代码和无效率。 我在互联网上看到了几个提到单例位置管理器的参考资料。而且我也听说要尽量避免单例。
问题:
我应该创建一个管理位置的单例类吗?如果没有,您会建议什么其他解决方案来避免这种重复的代码?
【问题讨论】:
“我也听说要尽可能避免单身。”这通常是基于人们使用愚蠢的模式来创建单例。或者有人说“单身人士很糟糕,因为他们做 X”,而答案不可避免地是“我的单身人士不做 X”。不使用单例的原因之一:如果你需要两个。 【参考方案1】:而且我也听说要尽量避免单身
如果应用程序运行的某个释放周期需要该数据,则上述语句是正确的,因此在完成单例后,从内存的角度来看,它会成为一个问题,因为它在整个应用程序生命周期中都保持活动状态,在您的情况下(所有 vcs 里面应用程序需要位置)最适合单例以避免重复 - 代码效率低下和内存问题
不用说 90% 的苹果类使用单例 e.x
URLSession.shared
NSNotificationCenter.default
UNUserNotificationCenter.current
UserDefaults.standard
文件管理器.default
【讨论】:
FileManager.default 实际上不是单例。您可以创建更多 FileManager 对象(具有不同的委托,因此在某些情况下它很有用)。【参考方案2】:没有硬性规定。 Apple 很清楚,可以实例化多个位置管理器。但是,如果您这样做,您可能会感到困惑,因为每个人都需要一个委托,每个人都需要自己的设置,等等。因此,您对这种方法保持警惕是正确的。
选择在应用程序的整个生命周期中持续存在的实例(例如,应用程序委托或根视图控制器)并使用位置管理器初始化实例属性是一种标准策略。没有任何理由将单例模式添加到混合中。您只需制作一次并保留它。
【讨论】:
这与职责分离不正确,事实上 appDelegate/rootVC 倾向于执行其指定的任务 也没有任何理由不创建单例。实际上,将东西塞进 AppDelegate 比创建几个(不同的)单例更糟糕。【参考方案3】:模式并不邪恶。这取决于用户。它们是针对特定问题的解决方案。这取决于您如何看待您的问题以及您想要实现的目标。
在您的情况下,您需要一个位置管理器实例贯穿您的应用并且在多个地方使用它,因此您需要一个包装器管理器。如果您只需要一种配置,那么使用单例是有意义的。
只要您需要,Apple 建议您对经理进行强有力的参考。 CLLocationManager - Apple Documentation
创建 CLLocationManager 类的一个实例,并将对它的强引用存储在应用程序的某处。 在涉及该对象的所有任务完成之前,需要保持对位置管理器对象的强引用。由于大多数位置管理器任务都是异步运行的,因此将位置管理器存储在局部变量中是不够的。
【讨论】:
【参考方案4】:如果您创建一个单例位置管理器,它必须做不同于其他单例的事情。您不能使用普通委托模式来通知其他对象有关位置更新和错误的信息,因为普通委托模式是一对一的关系。您必须使用多个委托(单例有一组感兴趣的对象,并且它向每个委托发送相同的消息,例如位置更新)。这是另一个关于为什么难以使用的问题:
Multiple Delegates in ios
你可以通过通知来解决这个问题,但我个人认为这是一种糟糕的模式(它过多地解耦了事情并且很难遵循责任路径)。
单例还必须跟踪是否有任何感兴趣的对象要求它停止或启动。如果他们都要求它停止,那么它应该关闭更新。如果只有一个人想要更新,则必须为其供电。搜索所有构建框架的人,只是为了使用网络指示器执行相同的任务,看看这有多麻烦。
如果请求位置时出现错误,您必须保存该错误,并且当(稍后)对象需要位置时,您必须重新传输错误。因此,您确实希望从一开始就连接所有感兴趣的对象并进行监听以避免这种情况。
我敢肯定,我能想出更多你必须处理的棘手案件。
中间选项是使用您的特殊设置、错误检查等创建一个位置管理器类,并在您需要时实例化其中一个。使用委托模式从中获取消息(大多数只是直接传递消息)。
【讨论】:
以上是关于我应该在 Swift 中使用单例位置管理器吗?的主要内容,如果未能解决你的问题,请参考以下文章