Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

delegating initializers in structs are not marked with 'convenience'

Tags:

swift

I keep getting this error and I don't understand why.

error: delegating initializers in structs are not marked with 'convenience'

This is what I have (as an example), a DeprecatedCurrency and a SupportedCurrency.

struct DeprecatedCurrency {
    let code: String
}

struct SupportedCurrency {
    let code: String
}

I then want to add a convenience init function for converting from the deprecated currency object to the new currency object. And this is what I have:

struct DeprecatedCurrency {
    let code: String
}

struct SupportedCurrency {
    let code: String

    convenience init(_ currecny: DeprecatedCurrency) { // error!!
        self.init(code: currecny.code)
    }

    init(code: String) {
        self.code = code
    }
}

What does this error even mean and how do I fix it?


I know that if we don't provide a default initializer, a initializer with signature init(code: String) will be automatically generated for us with struct in Swift. So by the end of the day, what I am really looking for is (if possible):

struct SupportedCurrency {
    let code: String

    convenience init(_ currecny: DeprecatedCurrency) { // error!!
        self.init(code: currecny.code)
    }
}
like image 939
Yuchen Avatar asked May 25 '17 15:05

Yuchen


3 Answers

Just remove the convenience, it is not required for struct.

From Swift documentation.

Initializers can call other initializers to perform part of an instance’s initialization. This process, known as initializer delegation, avoids duplicating code across multiple initializers.

They haven't mentioned using convenience. It is convenience in semantic but doesn't require the keyword.

struct DeprecatedCurrency {
    let code: String
}

struct SupportedCurrency {
    let code: String

    init(_ currency: DeprecatedCurrency) { // error!!
        self.init(code: currency.code)
    }

    init(code: String) {
        self.code = code
    }
}
like image 155
Rahul Avatar answered Oct 02 '22 15:10

Rahul


structs don't need the word convenience

Try this:

struct SupportedCurrency {
    let code: String

    init(_ currency: DeprecatedCurrency) { // error!!
        self.init(code: currency.code)
    }

    init(code: String) {
        self.code = code
    }
}

The question is not why don't we put convenience for structs but why do we put convenience for classes. The reason is that classes have inheritance. With a class you need to call the super class's designated constructor (not sure if that is the correct terminology, it comes from Objective-C's initialsers.. The word convenience marks the constructor as "not the designated constructor".

like image 38
JeremyP Avatar answered Oct 02 '22 15:10

JeremyP


One option is to add the new init in an extension of your struct. This way, you wont loose the default auto generated memberwise initialiser.

struct SupportedCurrency {
    let code: String

}

extension SupportedCurrency {
   init(_ currency: DeprecatedCurrency) {
        self.init(code: currency.code)
    }
}

From Apple docs

NOTE

If you want your custom value type to be initializable with the default initializer and memberwise initializer, and also with your own custom initializers, write your custom initializers in an extension rather than as part of the value type’s original implementation. For more information, see Extensions.

like image 28
Vishal Singh Avatar answered Oct 02 '22 16:10

Vishal Singh