0
votes

I'm trying to create a second failable convenience initializer to use because I want to make two API calls and this second failable initializer contains all the properties I'll get from the original API unlike the first failable initializer that will contain all the original properties plus a few additional ones I've added on which I'll be posting to firebase.

class Alcohol {
    var id: Int
    var companyName: String
    var address: String
    var city: String
    var state: String
    var postal: String
    var country: String
    var phone: String
    var email: String
    var url: String
    var checkedBy: String
    var notes: String
    var status: String
    var statusColor: String
    var identifier: NSUUID?
    var barnivoreChecked: Bool?
    var alcoholType: AlcoholType?

    // This failable init is for the information I'll be retrieving from firebase.

    init?(dictionary: [String: AnyObject], type: AlcoholType) {
        guard
            let id = dictionary[Constants.kID] as? Int,
            let companyName = dictionary[Constants.kCompanyName] as? String,
            let address = dictionary[Constants.kAddress] as? String,
            let city = dictionary[Constants.kCity] as? String,
            let state = dictionary[Constants.kState] as? String,
            let postal = dictionary[Constants.kPostal] as? String,
            let country = dictionary[Constants.kCountry] as? String,
            let phone = dictionary[Constants.kPhone] as? String,
            let email = dictionary[Constants.kEmail] as? String,
            let url = dictionary[Constants.kURL] as? String,
            let checkedBy = dictionary[Constants.kCheckedBy] as? String,
            let notes = dictionary[Constants.kNotes] as? String,
            let status = dictionary[Constants.kStatus] as? String,
            let statusColor = dictionary[Constants.kStatusColor] as? String,
            let barnivoreChecked = dictionary[Constants.kBarnivoreChecked] as? Bool else { return nil }

        self.id = id
        self.companyName = companyName
        self.address = address
        self.city = city
        self.state = state
        self.postal = postal
        self.country = country
        self.phone = phone
        self.email = email
        self.url = url
        self.checkedBy = checkedBy
        self.notes = notes
        self.status = status
        self.statusColor = statusColor
        self.barnivoreChecked = barnivoreChecked
        self.alcoholType = type
    }

    // This failable initializer has all the original properties I want to get from the initial API which I'll be retrieving the information from.

    convenience init?(barnivoreDictionary: [String: AnyObject]) {
        guard
            let id = barnivoreDictionary[Constants.kID] as? Int,
            let companyName = barnivoreDictionary[Constants.kCompanyName] as? String,
            let address = barnivoreDictionary[Constants.kAddress] as? String,
            let city = barnivoreDictionary[Constants.kCity] as? String,
            let state = barnivoreDictionary[Constants.kState] as? String,
            let postal = barnivoreDictionary[Constants.kPostal] as? String,
            let country = barnivoreDictionary[Constants.kCountry] as? String,
            let phone = barnivoreDictionary[Constants.kPhone] as? String,
            let email = barnivoreDictionary[Constants.kEmail] as? String,
            let url = barnivoreDictionary[Constants.kURL] as? String,
            let checkedBy = barnivoreDictionary[Constants.kCheckedBy] as? String,
            let notes = barnivoreDictionary[Constants.kNotes] as? String,
            let status = barnivoreDictionary[Constants.kStatus] as? String,
            let statusColor = barnivoreDictionary[Constants.kStatusColor] as? String else {
                self.init(id: 0, companyName: "", address: "", city: "", state: "", postal: "", country: "", phone: "", email: "", url: "", checkedBy: "", notes: "", status: "", statusColor: "", alcoholType: alcoholType! )
                return nil
        }

        self.id = id
        self.companyName = companyName
        self.address = address
        self.city = city
        self.state = state
        self.postal = postal
        self.country = country
        self.phone = phone
        self.email = email
        self.url = url
        self.checkedBy = checkedBy
        self.notes = notes
        self.status = status
        self.statusColor = statusColor
        self.alcoholType = nil
    }

    init(id: Int, companyName: String, address: String, city: String, state: String, postal: String, country: String, phone: String, email: String, url: String, checkedBy:String, notes: String, status: String, statusColor: String, barnivoreChecked: Bool = true, alcoholType: AlcoholType) {

        self.id = id
        self.companyName = companyName
        self.address = address
        self.city = city
        self.state = state
        self.postal = postal
        self.country = country
        self.phone = phone
        self.email = email
        self.url = url
        self.checkedBy = checkedBy
        self.notes = notes
        self.status = status
        self.statusColor = statusColor
        self.identifier =  NSUUID()
        self.barnivoreChecked = barnivoreChecked
        self.alcoholType = alcoholType
    }
}

Unfortunately I get an error stating:

"self" used before self.init call.

And if I do try to just use self.init(), I get the error:

Cannot invoke 'Alcohol.init' with no arguments.

Any help or suggestions would be much appreciated.

1
Use super.init(), or (better) override init() { super.init() } - user1232690

1 Answers

1
votes

In Swift 3, a convenience initializer must call a designated initializer in the same class before any attempt to access self is made in the convenience initializer.

I suggest you change your convenience initializer to be like this:

convenience init?(barnivoreDictionary: [String: AnyObject]) {
    guard
        let id = barnivoreDictionary[Constants.kID] as? Int,
        let companyName = barnivoreDictionary[Constants.kCompanyName] as? String,
        let address = barnivoreDictionary[Constants.kAddress] as? String,
        let city = barnivoreDictionary[Constants.kCity] as? String,
        let state = barnivoreDictionary[Constants.kState] as? String,
        let postal = barnivoreDictionary[Constants.kPostal] as? String,
        let country = barnivoreDictionary[Constants.kCountry] as? String,
        let phone = barnivoreDictionary[Constants.kPhone] as? String,
        let email = barnivoreDictionary[Constants.kEmail] as? String,
        let url = barnivoreDictionary[Constants.kURL] as? String,
        let checkedBy = barnivoreDictionary[Constants.kCheckedBy] as? String,
        let notes = barnivoreDictionary[Constants.kNotes] as? String,
        let status = barnivoreDictionary[Constants.kStatus] as? String,
        let statusColor = barnivoreDictionary[Constants.kStatusColor] as? String else {
            return nil
    }

    self.init(id: id, companyName: companyName, address: address, city: city, state: state, postal: postal, country: country, phone: phone, email: email, url: url, checkedBy: checkedBy, notes: notes, status: status, statusColor: statusColor, alcoholType: alcoholType)
}

Note that you don't need to call self.init... inside the guard.