简体   繁体   English

我应该在Swift中使用单例位置管理器吗?

[英]Should I use a singleton location manager in Swift?

Context: 内容:

My app needs the user's current location in several unrelated view controllers and, as of now, I'm creating a CLLocationManager in each of these controllers and requesting the current location over and over. 我的应用程序需要用户在几个不相关的视图控制器中的当前位置,到目前为止,我正在每个这些控制器中创建一个CLLocationManager,并一遍又一遍地请求当前位置。

However, it doesn't look right to me. 但是,这对我来说并不正确。 It's duplicated code and inneficient . 它是重复的代码 ,是无效的 I've seen several references on the internet mentioning a singleton location manager. 我在互联网上看到过一些提及单身人士位置管理器的参考。 And I also heard to avoid singletons as much as possible. 我还听说尽量避免单身。

Question: 题:

Should I create a singleton class that manages the location? 我应该创建一个管理位置的单例类吗? If not, what other solution would you suggest to avoid this duplicated code? 如果没有,您建议采用什么其他解决方案来避免重复的代码?

And I also heard to avoid singletons as much as possible 我还听说尽量避免单身

The above statement is correct in case that some dealoocated cycle of the app run needs that data so after it finishes the singleton becomes a problem from memory perspective as it stays alive all the app life cycle , in your case ( all vcs inside the app needs the location ) is the best fit for a singleton to avoid the duplication - less-efficient code and high memory issues 上面的陈述是正确的,以防应用程序运行的某些脱循环周期需要该数据,因此从内存的角度来看,完成单例操作后,它会在整个应用程序生命周期中保持有效(在您的情况下)(应用程序内部的所有vcs都需要)位置)最适合单身人士避免重复-代码效率较低且内存过多

Needless to say 90% of apple classes uses singletons ex 不用说90%的苹果课程使用ex

URLSession.shared URLSession.shared

NSNotificationCenter.default NSNotificationCenter.default

UNUserNotificationCenter.current UNUserNotificationCenter.current

UserDefaults.standard UserDefaults.standard

FileManager.default FileManager.default

There is no hard and fast rule. 没有硬性规定。 Apple is quite clear that it's fine to instantiate more than one location manager. 苹果非常清楚,实例化多个位置管理器是可以的。 However, if you do that, you might confuse yourself, because each will need a delegate, each will need its own settings, and so forth. 但是,如果这样做,您可能会感到困惑,因为每个人都需要一个委托,每个人都需要自己的设置,依此类推。 Thus, you are right to be wary of that approach. 因此,对这种方法保持警惕是正确的。

It is a standard strategy to pick an instance that persists throughout the life of your app — your app delegate, or your root view controller, for example — and initialize an instance property with a location manager. 这是一种标准策略,选择一个在应用程序的整个生命周期内都存在的实例(例如,您的应用程序委托或您的根视图控制器),并使用位置管理器初始化实例属性。 There is no reason whatever to add the Singleton pattern to the mix; 没有理由在混合中添加Singleton模式。 you simply make one once and keep hold of it. 您只需制造一个就可以了。

Patterns are not evil. 模式不是邪恶的。 It depends on the user. 这取决于用户。 They are solutions for a specific problems. 它们是针对特定问题的解决方案。 It depends on how you see your problem and what you want to achieve. 这取决于您如何看待问题以及想要实现的目标。

In your case, you need a location manager instance through out your app and you use it in multiple places, so you need a wrapper manager. 在您的情况下,您需要在整个应用程序中使用一个位置管理器实例,并在多个地方使用它,因此您需要一个包装器管理器。 If you only need one configuration, then it makes sense to use singleton. 如果只需要一种配置,则使用单例是有意义的。

Apple is recommending to have a strong reference of the manager as long as you need it. 苹果建议您在需要时为经理提供强有力的参考。 CLLocationManager - Apple Documentation CLLocationManager-Apple文档

Create an instance of the CLLocationManager class and store a strong reference to it somewhere in your app. 创建CLLocationManager类的实例,并将对其的强大引用存储在您的应用程序中的某个位置。 Keeping a strong reference to the location manager object is required until all tasks involving that object are complete. 在完成涉及该对象的所有任务之前,必须保持对位置管理器对象的强烈引用。 Because most location manager tasks run asynchronously, storing your location manager in a local variable is insufficient. 由于大多数位置管理器任务都是异步运行的,因此将位置管理器存储在本地变量中是不够的。

If you create a singleton location manager it has to do things differently than other singletons. 如果创建一个单例位置管理器,则它必须执行与其他单例不同的操作。 You can't use the normal delegate pattern for it to inform other objects about the location updates and errors because the normal delegate pattern is a one-to-one relationship. 您不能使用普通的委托模式来通知其他对象有关位置更新和错误的信息,因为普通的委托模式是一对一的关系。 You have to use multiple delegates (the singleton has an array of interested objects and it sends the same message, eg location update, to each one). 您必须使用多个委托(单例包含一组感兴趣的对象,并且向每个对象发送相同的消息,例如位置更新)。 Here's another question about why that's difficult to use: 这是另一个为什么很难使用的问题:

Multiple Delegates in iOS iOS中的多个代表

You can get around that with notifications but personally I think that's a bad pattern (it decouples things too much and makes it hard to follow paths of responsibility). 您可以通过通知来解决这个问题,但就我个人而言,我认为这是一个糟糕的模式(它使事情之间的耦合度过高,并且很难遵循责任的道路)。

The singleton also has to keep track of whether any of its interested objects asked it to stop or start. 单例还必须跟踪其感兴趣的任何对象是否要求其停止或启动。 If they've all asked it to stop then it should power down the updates. 如果他们都要求它停止,则应该关闭更新。 If just one wants updates it has to power them back up. 如果仅一个人想要更新,则必须为其供电。 Search for all the people building frameworks just to do the same task with the network indicator to see how much trouble this is. 搜索所有构建框架的人员,只是为了通过网络指示器执行相同的任务,以查看这有多麻烦。

If there's an error with requesting location you have to save that error and when (some later time) an object wants location, you have to retransmit the error. 如果请求位置时出错,则必须保存该错误,并且(稍后)对象要定位时,必须重新发送该错误。 So really you want to have all interested objects connected and listening from the start to avoid that scenario. 因此,实际上,您希望一开始就将所有感兴趣的对象连接起来并进行监听,以免发生这种情况。

I'm sure I could think of more hairy cases that you'd have to deal with. 我敢肯定,我会想到您需要处理的其他问题。

The in-between option is to create a location manager class with your special setup, error checking and so on, and instantiate one of those whenever you need it. 中间选项是使用特殊设置,错误检查等创建位置管理器类,并在需要时实例化其中之一。 Use the delegate pattern to get messages from it (most will just be passing the messages along directly). 使用委托模式从中获取消息(大多数将直接传递消息)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM