Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use global variables in Swift

I'm learning Swift and iOS app development and I was wondering in which cases (if there are some) I should use global variables and constants in an iOS app.

Global variables are variables that are defined outside of any function, method, closure, or type context. Local variables are variables that are defined within a function, method, or closure context.

Using global variables usually seems inelegant and not advisable (it is in fact not recommended by most guides and tutorials) and to pass data between view controller I use the prepareForSegue(_: sender:) method.

There are some cases however where it seems to me that the use of globals would make the code simpler and faster.

For example Apple recommends to store a NSDateFormatter or a NSNumberFormatter for each format pattern and not to recreate or to change one every time it is needed. In an app I'm developing to learn the language, most of the view controllers use a NSDateFormatter and a NSNumberFormatter and creating a new one for each view controller might not be a good idea. I could pass it with prepareForSegue, but I thought that maybe in this case it would be better to use a global var holding an instance of the formatter that every view controller could use.

So are there any cases where I should use global variables?

like image 944
Lorenzo Rossi Avatar asked Dec 26 '15 22:12

Lorenzo Rossi


1 Answers

Every time you find yourself using a global, you need to take a step back and think hard about what the data is and how it relates to the rest of your app. It is easy to say you need to avoid globals, the hard part is knowing the best alternative for the scenario, something even veteran Cocoa developers will disagree on.

In the singleton pattern, you create a class and stash your global inside it. This is often offered as a solution because it's the easiest to prescribe and follow, but many times I wonder if it is a solution at all. Wrapping a class around a global doesn't give you any additional protections. After all, the class itself is now a global entity. I like to think of the Singleton pattern as a way of organizing, categorizing and containing globals as opposed to avoiding globals.

Singletons should be reserved for the tentpoles of your application like database or remote backend connection handlers. Every Cocoa/CocoaTouch App comes with a built in Singleton, the AppDelegate, and in many cases, assorted things can go there.

In many cases, the "correct" solution is to pass the data along, such as passing data between view controllers in the prepareForSegue: class. This is well described in Andy Matuschak's brilliant WWDC 2014 session, Advanced iOS Application Architecture and Patterns. I agree with you though, that this doesn't apply in your example. In your example, you're not handing relevant data between two views, you're trying to share a common facility to conserver resources.

For your specific example, I would use a Singleton or similar pattern. One way that makes sense to me is to stash them inside their corresponding classes using extensions. For example:

extension NSDateFormatter {
  static let newDateFormatter = NSDateFormatter()
}

// use it in your app like this:
NSDateFormatter.newDateFormatter

Like commenters said, this is a matter of opinion. Also keep in mind that Swift is still young and while it borrows heavily from Cocoa out of necessity, idioms are still evolving.

like image 116
hashemi Avatar answered Sep 30 '22 19:09

hashemi