2

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.

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?

rfarias
  • 1,296
  • 10
  • 15
  • "And I also heard to avoid singletons as much as possible." That's usually based on people using stupid patterns to create singletons. Or people saying "Singletons are bad because they do X" to which the answer is inevitably "My Singletons don't do X". There is ONE reason not to use singletons: If you need two. – gnasher729 Jun 12 '19 at 22:32

4 Answers4

2

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

Needless to say 90% of apple classes uses singletons e.x

URLSession.shared

NSNotificationCenter.default

UNUserNotificationCenter.current

UserDefaults.standard

FileManager.default

Community
  • 1
  • 1
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • FileManager.default is actually not a singleton. You can create more FileManager objects (with different delegates, so there will be cases where it is useful). – gnasher729 Jun 12 '19 at 22:27
1

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; you simply make one once and keep hold of it.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • This is not correct from separation of duties fact the appDelegate/rootVC is en tended to do what it's designated for – Shehata Gamal Jun 12 '19 at 21:10
  • There's also no reason whatsoever not to create a singleton. Actually, stuffing things into AppDelegate is worse than creating a few (different) singletons. – gnasher729 Jun 12 '19 at 22:29
1

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

Create an instance of the CLLocationManager class and store a strong reference to it somewhere in your app. 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.

Mustafa Ahmed
  • 422
  • 2
  • 8
1

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, e.g. location update, to each one). Here's another question about why that's difficult to use:

Multiple Delegates in 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).

nevan king
  • 112,709
  • 45
  • 203
  • 241