Defining Global constants in Swift

Let’s have a look on all possible ways

Credit: pexels.com

All apps define global constants in either one or other way. Some people think all constants should be part of global constants no matter whether it’s used only at one place or multiple places. In starting everything looks good but as your app grows you find it difficult to manage. IMHO it’s better to not create global constant if you are using constant only at a single place.

You can define constants on a type rather than on an instance of that type using type properties. To declare a type property as a constant simply use static let. Type properties declared in this way are generally preferred over global constants because they are easier to distinguish from instance properties. Let’s explore ways to declare global constants when it’s being used at multiple places:

Using struct

struct is value type and can be use to define constants. You can create hierarchy too using nested struct.

struct Constants {
static let width: CGFloat = 100
static let height:CGFloat = 100
}

Constant can be accessed like this:

Constants.width

nested struct will look like this:

struct ConstantsStruct { 
static let lineHeight: CGFloat = 18
  struct ContainerSize {
static let width: CGFloat = 100
static let height:CGFloat = 100
}
}

Drawback with this approach is, you would end up in creating instance of struct.

let instance = ConstantsStruct()   // Useless, but legal

2. Using case-less enum:

Why named case-less enum?

Generally, when someone speaks about enum, a case comes in our mind which is the same concept in all languages. If you specify case in enum then you can instantiate it. case-less enum means you won’t specify any case. You will just specify type properties.

enums are also value type but case-less enum won’t allow you to create instance.

enum ConstantsEnum {
static let width: CGFloat = 100
static let height: CGFloat = 50
}
The advantage of using a case-less enumeration is that it can’t accidentally be instantiated and works as a pure namespace.

If you try to create instance of ConstantsEnum you will end up with error:

let instance = ConstantsEnum()    // error: 'LayoutConstants' cannot be constructed because it has no accessible initializers

Therefore if you are just looking for something to serve as a namespace for some static members, an enum is preferred as you can’t accidentally create an instance.

Example Usage:

enum ConstantsEnum {
static let xxx = 500

enum xxxx {
static let .........
}
}

3. Swift Extensions:

Instead of declaring a global constant, we can extend the type of the constant. This approach is useful when you are passing key name in notification center code.

extension Notification.Name {
// Notifications
static let customNotification = Notification.Name("customNotification")
}
func postNotification() {
NotificationCenter.default.post(name: .customNotification, object: nil)
}

Implicit Member Expression:

An implicit member expression is a way to access a member of a type, such as an enumeration case or a type method, in a context where type inference can determine the implied type.

extension Double {
public static let kRectX = 30.0
public static let kRectY = 30.0
public static let kRectWidth = 30.0
public static let kRectHeight = 30.0
}

public func makeRect() -> CGRect {
return CGRect(x: .kRectX, y: .kRectY, width: .kRectWidth, height: .kRectHeight)
}

As you define methods and properties, Swift offers implicit access to instance methods and properties without a “self” prefix. Swift implicit also applies to class methods, enum cases, auto layout etc.

Example in Swift Standard Library:

public static let background: DispatchQoS
public static let userInitiated: DispatchQoS

Conclusion:

If you have many global constants in a project then it’s good to group constants based on feature in separate files. Constant creation approach varies from context to context.

Personally, I prefer to create constants using a case-less enum.


Thanks for reading article. If you have any doubt please add in below comment section.

You can catch me at:

Linkedin: Aaina Jain

Twitter: __aainajain