Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define static constant in a class in swift

Tags:

swift

I have these definition in my function which work

class MyClass {
    func myFunc() {
        let testStr = "test"
        let testStrLen = countElements(testStr)
    }
}

But if I move 'testStr' and 'testStrLen' to the class level, it won't compile. It said 'MyClass.Type does not have a member named 'testStr'.

class MyClass {
    let testStr = "test"
    let testStrLen = countElements(testStr)

    func myFunc() {

    }
}

How can I fix this? I don't want to pay the penalty for counting len of a constant 'test' everytime.

Based on my understanding of the comments below, I need to do this:

class MyClass {
    let testStr = "test"
    let testStrLen = countElements("test")

    func myFunc() {

    }
}

Is there a way I don't need to type/enter "test" twice? Thanks.

like image 720
n179911 Avatar asked Sep 18 '14 17:09

n179911


People also ask

What is a static VAR in Swift?

When you define a static var/let into a class (or struct), that value will be shared among all the instances (or values). static variables/class are variables can be accessed without need of creation of any instance/object.

How do you set a static variable in Swift?

You create static variable by appending static keyword in front of your variable declaration. We will be using playground to explore more. When we define any variable as let, it means it's values cannot be modified, On the other hand if we define any variable as var it means it's values can be modified.

How do you declare a constant in Swift?

In Swift, constants are declared using the let keyword. In a similar fashion to variables, the let keyword is followed by the name of the constant you want to declare and then a type annotation (a colon, a space and then the type of data you want to store in the constant).

Where static variables are stored in Swift?

data segment stores Swift static variables, constants and type metadata.


3 Answers

Perhaps a nice idiom for declaring constants for a class in Swift is to just use a struct named MyClassConstants like the following.

struct MyClassConstants{
    static let testStr = "test"
    static let testStrLength = countElements(testStr)

    static let arrayOfTests: [String] = ["foo", "bar", testStr]
}

In this way your constants will be scoped within a declared construct instead of floating around globally.

Update

I've added a static array constant, in response to a comment asking about static array initialization. See Array Literals in "The Swift Programming Language".

Notice that both string literals and the string constant can be used to initialize the array. However, since the array type is known the integer constant testStrLength cannot be used in the array initializer.

like image 180
Martin Woolstenhulme Avatar answered Oct 22 '22 18:10

Martin Woolstenhulme


Adding to @Martin's answer...

If anyone planning to keep an application level constant file, you can group the constant based on their type or nature

struct Constants {
    struct MixpanelConstants {
        static let activeScreen = "Active Screen";
    }
    struct CrashlyticsConstants {
        static let userType = "User Type";
    }
}

Call : Constants.MixpanelConstants.activeScreen

UPDATE 5/5/2019 (kinda off topic but 🤷🏽‍♂️)

After reading some code guidelines & from personal experiences it seems structs are not the best approach for storing global constants for a couple of reasons. Especially the above code doesn't prevent initialization of the struct. We can achieve it by adding some boilerplate code but there is a better approach

ENUMS

The same can be achieved using an enum with a more secure & clear representation

enum Constants {
    enum MixpanelConstants: String {
        case activeScreen = "Active Screen";
    }
    enum CrashlyticsConstants: String {
        case userType = "User Type";
    }
}

print(Constants.MixpanelConstants.activeScreen.rawValue)
like image 38
Clement Prem Avatar answered Oct 22 '22 19:10

Clement Prem


If I understand your question correctly, you are asking how you can create class level constants (static - in C++ parlance) such that you don't a) replicate the overhead in every instance, and b have to recompute what is otherwise constant.

The language has evolved - as every reader knows, but as I test this in Xcode 6.3.1, the solution is:

import Swift

class MyClass {
    static let testStr = "test"
    static let testStrLen = count(testStr)

    init() {
        println("There are \(MyClass.testStrLen) characters in \(MyClass.testStr)")
    }
}

let a = MyClass()

// -> There are 4 characters in test

I don't know if the static is strictly necessary as the compiler surely only adds only one entry per const variable into the static section of the binary, but it does affect syntax and access. By using static, you can refer to it even when you don't have an instance: MyClass.testStrLen.

like image 44
Chris Conover Avatar answered Oct 22 '22 19:10

Chris Conover