简体   繁体   中英

Why does Swift give me a compiler error when my convenience initializer runs self.init inside if an if-let statement?

Here is a sample of code that I'd like to get compiling:

class Fruit {
    var name: String

    init(name: String, season: String) {
        self.name = name
    }

    convenience init?(data: [String: String]) {
        if let name = data["name"], region = data["region"] {
            self.init(name: name, season: region)
        }
    }
}

The compiler error is "Use of 'self' in delegating initializer before self.init is called"

If the initializer is failable, shouldn't I be able to have code paths that don't run any initializer? This code compiles if you add an else with an initializer:

convenience init?(data: [String: String]) {
    if let name = data["name"], region = data["region"] {
        self.init(name: name, season: region)
    } else {
        self.init(name: "test", season: "test")
    }
}

The error message is perhaps misleading. You must explicitly return nil if the initialization fails, as stated in the documentation "Failable Initializers" :

You write return nil within a failable initializer to indicate a point at which initialization failure can be triggered.

Which means in your case that you have to add an else case if the optional binding fails:

convenience init?(data: [String: String]) {
    if let name = data["name"], region = data["region"] {
        self.init(name: name, season: region)
    } else {
        return nil
    }
}

Alternatively with guard :

convenience init?(data: [String: String]) {
    guard let name = data["name"], region = data["region"] else {
        return nil
    }
    self.init(name: name, season: region)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM