Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'self' used before all stored properties are initialized in struct

I want CurrendData.location to get its random value once CurrentData gets initialized. I came up following code:

struct CurrentData {
    var size: (x: Int, y: Int)
    var location: (x: Int, y: Int)
        
    init(size: (x: Int, y: Int)) {
        self.size = size
        self.location = (getRandom(size.x), getRandom(size.y)) //error
    }
    
    private func getRandom (_ value:Int) -> Int {
        return Int.random(in: 0...value-1)
    }
}

But I get this error: "'self' used before all stored properties are initialized". How can it be fixed?

like image 770
Anatolii Rudenko Avatar asked Sep 01 '25 20:09

Anatolii Rudenko


2 Answers

getRandom is an instance method, so it is called on self (however, Swift lets you omit self when accessing instance methods/properties).

If you want to be able to call a function from init, you need to declare it as a static method rather than an instance method. You can then call the static method by writing out the type name (CurrentData) or simply using Self.

struct CurrentData {
    var size: (x: Int, y: Int)
    var location: (x: Int, y: Int)
        
    init(size: (x: Int, y: Int)) {
        self.size = size
        self.location = (Self.getRandom(size.x), Self.getRandom(size.y))
    }
    
    private static func getRandom (_ value:Int) -> Int {
        Int.random(in: 0...value-1)
    }
}
like image 183
Dávid Pásztor Avatar answered Sep 03 '25 22:09

Dávid Pásztor


Instead defining your getRandom as an instance method, define it as a static one, then reference it by a type name (CurrentData) or Self

struct CurrentData {
    var size: (x: Int, y: Int)
    var location: (x: Int, y: Int)
        
    init(size: (x: Int, y: Int)) {
        self.size = size
        location = (Self.getRandom(size.x), Self.getRandom(size.y))
    }
    
    private static func getRandom (_ value:Int) -> Int {
        Int.random(in: 0...value-1)
    }
}

Other solution is to define your locationproperty as a lazy one, then the self is accessible and the location will be executed only once and after being called in the code.

struct CurrentData {
    var size: (x: Int, y: Int)
    lazy var location: (x: Int, y: Int) = {
        (getRandom(size.x), getRandom(size.y))
    }()
        
    init(size: (x: Int, y: Int)) {
        self.size = size
    }
    
    private func getRandom (_ value:Int) -> Int {
        Int.random(in: 0...value-1)
    }
}
like image 34
Blazej SLEBODA Avatar answered Sep 03 '25 22:09

Blazej SLEBODA