Global constants file in Swift

IosObjective CSwift

Ios Problem Overview


In my Objective-C projects I often use a global constants file to store things like notification names and keys for NSUserDefaults. It looks something like this:

@interface GlobalConstants : NSObject

extern NSString *someNotification;

@end

@implementation GlobalConstants

NSString *someNotification = @"aaaaNotification";

@end

How do I do exactly the same thing in Swift?

Ios Solutions


Solution 1 - Ios

Structs as namespace

IMO the best way to deal with that type of constants is to create a Struct.

struct Constants {
    static let someNotification = "TEST"
}

Then, for example, call it like this in your code:

print(Constants.someNotification)

Nesting

If you want a better organization I advise you to use segmented sub structs

struct K {
    struct NotificationKey {
        static let Welcome = "kWelcomeNotif"
    }
    
    struct Path {
        static let Documents = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
        static let Tmp = NSTemporaryDirectory()
    }
}

Then you can just use for instance K.Path.Tmp

Real world example

This is just a technical solution, the actual implementation in my code looks more like:

struct GraphicColors {

    static let grayDark = UIColor(0.2)
    static let grayUltraDark = UIColor(0.1)

    static let brown  = UIColor(rgb: 126, 99, 89)
    // etc.
}

and


enum Env: String {
    case debug
    case testFlight
    case appStore
}

struct App {
    struct Folders {
        static let documents: NSString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
        static let temporary: NSString = NSTemporaryDirectory() as NSString
    }
    static let version: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
    static let build: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String

    // This is private because the use of 'appConfiguration' is preferred.
    private static let isTestFlight = Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt"

    // This can be used to add debug statements.
    static var isDebug: Bool {
        #if DEBUG
        return true
        #else
        return false
        #endif
    }

    static var env: Env {
        if isDebug {
            return .debug
        } else if isTestFlight {
            return .testFlight
        } else {
            return .appStore
        }
    }
}

Solution 2 - Ios

I am abit late to the party.

No matter here's how i manage the constants file so that it makes more sense to developers while writing code in swift.

FOR URL:

//URLConstants.swift

  struct APPURL {
    
    private struct Domains {
        static let Dev = "http://test-dev.cloudapp.net"
        static let UAT = "http://test-UAT.com"
        static let Local = "192.145.1.1"
        static let QA = "testAddress.qa.com"
    }
    
    private  struct Routes {
        static let Api = "/api/mobile"
    }
    
    private  static let Domain = Domains.Dev
    private  static let Route = Routes.Api
    private  static let BaseURL = Domain + Route
    
    static var FacebookLogin: String {
        return BaseURL  + "/auth/facebook"
    }
}

For CUSTOMFONTS:

//FontsConstants.swift
struct FontNames {
    
    static let LatoName = "Lato"
    struct Lato {
        static let LatoBold = "Lato-Bold"
        static let LatoMedium = "Lato-Medium"
        static let LatoRegular = "Lato-Regular"
        static let LatoExtraBold = "Lato-ExtraBold"
    }
}

FOR ALL THE KEYS USED IN APP

//KeyConstants.swift
    struct Key {
        
        static let DeviceType = "iOS"
        struct Beacon{
            static let ONEXUUID = "xxxx-xxxx-xxxx-xxxx"
        }

        struct UserDefaults {
            static let k_App_Running_FirstTime = "userRunningAppFirstTime"
        }

        struct Headers {
            static let Authorization = "Authorization"
            static let ContentType = "Content-Type"
        }
        struct Google{
            static let placesKey = "some key here"//for photos
            static let serverKey = "some key here"
        }
        
        struct ErrorMessage{
            static let listNotFound = "ERROR_LIST_NOT_FOUND"
            static let validationError = "ERROR_VALIDATION"
        }
    }

FOR COLOR CONSTANTS:

//ColorConstants.swift
struct AppColor {
    
    private struct Alphas {
        static let Opaque = CGFloat(1)
        static let SemiOpaque = CGFloat(0.8)
        static let SemiTransparent = CGFloat(0.5)
        static let Transparent = CGFloat(0.3)
    }
    
    static let appPrimaryColor =  UIColor.white.withAlphaComponent(Alphas.SemiOpaque)
    static let appSecondaryColor =  UIColor.blue.withAlphaComponent(Alphas.Opaque)
    
    struct TextColors {
        static let Error = AppColor.appSecondaryColor
        static let Success = UIColor(red: 0.1303, green: 0.9915, blue: 0.0233, alpha: Alphas.Opaque) 
    }
    
    struct TabBarColors{
        static let Selected = UIColor.white
        static let NotSelected = UIColor.black
    }
    
    struct OverlayColor {
        static let SemiTransparentBlack = UIColor.black.withAlphaComponent(Alphas.Transparent)
        static let SemiOpaque = UIColor.black.withAlphaComponent(Alphas.SemiOpaque)
        static let demoOverlay = UIColor.black.withAlphaComponent(0.6)
    }
}

You can wrap these all files in a common group named Constants in your Xcode Project.

And for more watch this video

Solution 3 - Ios

Although I prefer @Francescu's way (using a struct with static properties), you can also define global constants and variables:

let someNotification = "TEST"

Note however that differently from local variables/constants and class/struct properties, globals are implicitly lazy, which means they are initialized when they are accessed for the first time.

Suggested reading: Global and Local Variables, and also Global variables in Swift are not variables

Solution 4 - Ios

Consider enumerations. These can be logically broken up for separate use cases.

enum UserDefaultsKeys: String {
    case SomeNotification = "aaaaNotification"
    case DeviceToken = "deviceToken"
}

enum PhotoMetaKeys: String {
    case Orientation = "orientation_hv"
    case Size = "size"
    case DateTaken = "date_taken"
}

One unique benefit happens when you have a situation of mutually exclusive options, such as:

for (key, value) in photoConfigurationFile {
    guard let key = PhotoMetaKeys(rawvalue: key) else {
        continue // invalid key, ignore it
    }
    switch (key) {
    case.Orientation: {
        photo.orientation = value
    }
    case.Size: {
        photo.size = value
    }
    }
}

In this example, you will receive a compile error because you have not handled the case of PhotoMetaKeys.DateTaken.

Solution 5 - Ios

Constant.swift

import Foundation

let kBaseURL = NSURL(string: "http://www.example.com/")

ViewController.swift

var manager = AFHTTPRequestOperationManager(baseURL: kBaseURL)

Solution 6 - Ios

Or just in GlobalConstants.swift:

import Foundation

let someNotification = "aaaaNotification"

Solution 7 - Ios

Like others have mentioned, anything declared outside a class is global.

You can also create singletons:

class TestClass {
    static let sharedInstance = TestClass()
    // Anything else goes here
    var number = 0
}

Whenever you want to use something from this class, you e.g. write:

TestClass.sharedInstance.number = 1

If you now write println(TestClass.sharedInstance.number) from anywhere in your project you will print 1 to the log. This works for all kinds of objects.

tl;dr: Any time you want to make everything in a class global, add static let sharedInstance = YourClassName() to the class, and address all values of the class with the prefix YourClassName.sharedInstance

Solution 8 - Ios

What I did in my Swift project
1: Create new Swift File
2: Create a struct and static constant in it.
3: For Using just use YourStructName.baseURL

Note: After Creating initialisation takes little time so it will show in other viewcontrollers after 2-5 seconds.

import Foundation

    struct YourStructName {
    static let MerchantID = "XXX"
    static let MerchantUsername = "XXXXX"
    static let ImageBaseURL = "XXXXXXX"
    static let baseURL = "XXXXXXX"
    }

Solution 9 - Ios

To have global constants in my apps, this is what I do in a separate Swift file:

import Foundation

struct Config {
    static let baseURL = "https://api.com"
    
    static APIKeys {
        static let token = "token"
        static let user = "user"
    }
    
    struct Notifications {
        static let awareUser = "aware_user"
    }
}

It's easy to use, and to call everywhere like this:

print(Config.Notifications.awareUser)

Solution 10 - Ios

Caseless enums can also be be used.

Advantage - They cannot be instantiated.

enum API {
    enum Endpoint {
        static let url1 = "url1"
        static let url2 = "url2"
    }
    enum BaseURL {
        static let dev = "dev"
        static let prod = "prod"
    }
}

Solution 11 - Ios

Learn from Apple is the best way.

For example, Apple's keyboard notification:

extension UIResponder {

    public class let keyboardWillShowNotification: NSNotification.Name

    public class let keyboardDidShowNotification: NSNotification.Name

    public class let keyboardWillHideNotification: NSNotification.Name

    public class let keyboardDidHideNotification: NSNotification.Name

}

Now I learn from Apple:

extension User {
    /// user did login notification
    static let userDidLogInNotification = Notification.Name(rawValue: "User.userDidLogInNotification")
}

What's more, NSAttributedString.Key.foregroundColor:

extension NSAttributedString {

    public struct Key : Hashable, Equatable, RawRepresentable {

        public init(_ rawValue: String)

        public init(rawValue: String)
    }
}

extension NSAttributedString.Key {

    /************************ Attributes ************************/

    @available(iOS 6.0, *)
    public static let foregroundColor: NSAttributedString.Key // UIColor, default blackColor

}

Now I learn form Apple:

extension UIFont {
    
    struct Name {
        
    }
    
}

extension UIFont.Name {
    
    static let SFProText_Heavy = "SFProText-Heavy"
    static let SFProText_LightItalic = "SFProText-LightItalic"
    static let SFProText_HeavyItalic = "SFProText-HeavyItalic"
    
}

usage:

let font = UIFont.init(name: UIFont.Name.SFProText_Heavy, size: 20)

Learn from Apple is the way everyone can do and can promote your code quality easily.

Solution 12 - Ios

For notifications you can use extension, something like this:

extension Notification.Name {
    static let testNotification = "kTestNotification"
}

And use it like NotificationCenter.default.post(name: .testNotification, object: nil)

Solution 13 - Ios

Swift 4 Version

If you want to create a name for NotificationCenter:

extension Notification.Name {
    static let updateDataList1 = Notification.Name("updateDataList1")
}

Subscribe to notifications:

NotificationCenter.default.addObserver(self, selector: #selector(youFunction), name: .updateDataList1, object: nil)

Send notification:

NotificationCenter.default.post(name: .updateDataList1, object: nil)

If you just want a class with variables to use:

class Keys {
    static let key1 = "YOU_KEY"
    static let key2 = "YOU_KEY"
}

Or:

struct Keys {
    static let key1 = "YOU_KEY"
    static let key2 = "YOU_KEY"
}

Solution 14 - Ios

Colors

extension UIColor {
    static var greenLaPalma: UIColor {
        return UIColor(red:0.28, green:0.56, blue:0.22, alpha:1.00)
    }
}

Fonts

enum CustomFontType: String {
    case avenirNextRegular = "AvenirNext-Regular",
    avenirDemiBold = "AvenirNext-DemiBold"
}

extension UIFont {
    static func getFont(with type: CustomFontType, size: CGFloat) -> UIFont {
		let font = UIFont(name: type.rawValue, size: size)!

		return font
	}
}

For other - everything the same as in accepted answer.

Solution 15 - Ios

According to the swift docs global variables are declared in file scope.

> Global variables are variables that are defined outside of any function, method, closure, or type context

Just create a swift file (E.g: Constnats.swift) and declare your constants there:

// Constants.swift

let SOME_NOTIF = "aaaaNotification"

and call it from anywhere in your project without the need to mention struct,enum or class name.

// MyViewController.swift

NotificationCenter.default.post(name: SOME_NOTIF, object: nil)

I think this is much better for code readability.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1028028View Question on Stackoverflow
Solution 1 - IosFrancescuView Answer on Stackoverflow
Solution 2 - IosAnish Parajuli 웃View Answer on Stackoverflow
Solution 3 - IosAntonioView Answer on Stackoverflow
Solution 4 - IosWilliam EntrikenView Answer on Stackoverflow
Solution 5 - IosKirit VaghelaView Answer on Stackoverflow
Solution 6 - IosChikabuZView Answer on Stackoverflow
Solution 7 - IosJacob RView Answer on Stackoverflow
Solution 8 - IosVinay Krishna GuptaView Answer on Stackoverflow
Solution 9 - IosAle MohamadView Answer on Stackoverflow
Solution 10 - IosPranav PravakarView Answer on Stackoverflow
Solution 11 - Ios无夜之星辰View Answer on Stackoverflow
Solution 12 - IosB. ShoeView Answer on Stackoverflow
Solution 13 - IosValeriyView Answer on Stackoverflow
Solution 14 - IosBohdan SavychView Answer on Stackoverflow
Solution 15 - IosSeif MeddebView Answer on Stackoverflow