David
David

Reputation: 2810

Swift: Use constant property to define another property fails

I'm trying to declare an array of a static size. I'd like a constant to define the size of the array.

I'm trying the following in Swift

class foo {
    let size = 10
    let myArray = [Int](count: size, repeatedValue: 0)
}

But this fails with an error,

'foo.Type' does not have a member named 'size'       

If I don't use the size constant, the compiler is happy with it but isn't what I'd like. And there's no #define capability that I'm aware of.

let myArray = [Int](count: 10, repeatedValue: 0)

Upvotes: 3

Views: 436

Answers (4)

Michael D.
Michael D.

Reputation: 106

With Swift 1.2 you can simply add static before let size, making it a class constant and as such defined before myArray is being defined:

class foo {
    static let size = 10
    let myArray = [Int](count: size, repeatedValue: 0)
}

Be aware though, that using size later in your code requires you to fully qualify it as foo.size.

Upvotes: 1

Steve Rosenberg
Steve Rosenberg

Reputation: 19524

One way is for it to be in a function. This worked in a playground:

import UIKit

class ViewController: UIViewController {

    var myArray = [Int]()

    func appendArray (#index: Int, value: Int) {
        myArray[index] = value
    }


    override func viewDidLoad() {
        super.viewDidLoad()

        let size = 10
        myArray = [Int](count: size, repeatedValue: 0)
        appendArray(index: 3, value: 4)
        println(myArray)

    }
}

Okay, I used a ViewController because it was convenient, but not necessary. No problem declaring the array out side of a function. I still used a function to create the array and used another one t change a value.

Upvotes: 0

Antonio
Antonio

Reputation: 72810

In swift self is unavailable until all class/struct properties have been initialized, and a subclass initializer has been called (in case of an inherited class).

In your case you are initializing properties outside of an initializer, but that doesn't change the result: you cannot initialize a variable implicitly referencing self (which you do when accessing to the size property).

However, size looks like a constant, and as such it's better to instantiate it once (as a static property) rather than having it created in each class instance. Swift doesn't support static class properties, but structs do, so a trick is to define an inner private struct, containing the static immutable properties you may need:

class foo {
    private struct Static {
        static let size = 10
    }

    let myArray = [Int](count: Static.size, repeatedValue: 0)
}

Upvotes: 3

Nate Cook
Nate Cook

Reputation: 93296

Swift gives you a couple ways to do this. The simplest, and most in line with the #define style you mention, is to declare size as a global constant:

let FOOSIZE = 10

class Foo {
    let myArray = [Int](count: FOOSIZE, repeatedValue: 0)
}

Alternatively, you can define myArray as a lazy variable, and use a closure to populate its value. By the time the closure is executed you'll be able to access self.size:

class Foo {
    let size = 10
    lazy var myArray: [Int] = { [Int](count: self.size, repeatedValue: 0) }()
}

Upvotes: 3

Related Questions