Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift 2.0: use of self in method call before stored properties are initialised

Just started looking at Swift this weekend. I'm creating an id for my class to quickly compare objects. I want an immutable id, so should use let.

Using var and initialising id to "" will fix "use of self in method call before stored properties are initialised" but then of course it's mutable. Every other question i've seen similar to this is regarding a super class / calling super.init, which I don't have. It's very frustrating, I don't know why it's not straightforward.

class MagicCard {

    let id:String
    let name: String
    let manaCost: Int
    let description: String
    let attack: Int
    let defence: Int

    init (name: String, manaCost: Int, description: String, attack: Int, defence: Int) {
        self.name = name
        self.manaCost = manaCost
        self.description = description
        self.attack = attack
        self.defence = defence
        id = generateRandomID()
    }

    private func generateRandomID() -> String {
        let charSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        let charSetArray = Array(charSet.characters)
        var id:String = ""
        for _ in (0..<10) {
            id.append(charSetArray[Int(arc4random()) % charSetArray.count])
        }
        return id
    }
}

func == (lhs: MagicCard, rhs: MagicCard) -> Bool {
    return lhs.id == rhs.id
}
like image 863
SparkyRobinson Avatar asked Aug 02 '15 11:08

SparkyRobinson


People also ask

Which type of property is initialized when it is accessed first in Swift?

Classes, structures and enumerations once declared in Swift 4 are initialized for preparing instance of a class. Initial value is initialized for stored property and also for new instances too the values are initialized to proceed further. The keyword to create initialization function is carried out by 'init()' method.

Do you have to initialize variables in Swift?

Variables and constants do not require initialization when declared. However, the variable or constant requires type annotation so that when the compiler reads the code line-by-line, it can determine the data type at the time of the build. A Use of undeclared type error will be thrown otherwise.

What do Initializers do in Swift?

Initializers are called to create a new instance of a particular type. In its simplest form, an initializer is like an instance method with no parameters, written using the init keyword: init() { // perform some initialization here.

How do you call an init method in Swift?

An initializer is a special type of function that is used to create an object of a class or struct. In Swift, we use the init() method to create an initializer. For example, class Wall { ... // create an initializer init() { // perform initialization ... } }


2 Answers

A hot-fix I can suggest is to make generateRandomID a class func. So make it like so :

private class func generateRandomID() -> String {

And call like this :

id = MagicCard.generateRandomID()
like image 179
s1ddok Avatar answered Dec 22 '22 04:12

s1ddok


The generateRandomID() method does not use or modify any properties of the instance, so one possible solution would be to make it a type (class) method:

private class func generateRandomID() -> String {
    // ...
    return id
}

and use it like

id = MagicCard.generateRandomID()

(as also written in the other answer while I was writing this).

You could also drop the method and use an "immediately evaluated closure":

id = { () -> String in
    // ...
    return id
}()

But if the intention of the id property is to make the objects Equatable then you don't need it at all. Classes are reference types and instances can be compared with the "identical to" operator:

func == (lhs: MagicCard, rhs: MagicCard) -> Bool {
    return lhs === rhs
}

which makes the id and the generateRandomID() method obsolete.

like image 23
Martin R Avatar answered Dec 22 '22 05:12

Martin R