Search code examples
jsonswiftinitializationswifty-jsonfailable

Swift Failable Initializer with SwiftyJSON


I’m trying to initialise a simple data model object with some JSON from SwiftyJSON. I’d like the initialiser to fail and return nil if any of the required JSON values aren’t present. Here’s my code:

class ProductCategory: NSObject {

  let id: String
  let sortOrder: Int
  let name: String
  let imageURL: String
  let ranges: [String]

  init?(json: JSON) {
    if let jsonID = json["id"].string,
       jsonSortOrder = json["sortOrder"].int,
       jsonName = json["name"].string,
       jsonImageURL = json["imageURL"].string {
      id = jsonID
      sortOrder = jsonSortOrder
      name = jsonName
      imageURL = jsonImageURL
      ranges = json["ranges"].arrayValue.map { $0.string! }
    } else {
      return nil
    }
  }
}

I’d expect this to work. In the event that we didn’t hit all those json values, simply return nil and bail out. However, I get an error on the return nil, stating:

All stored properties of a class instance must be initialized before returning nil from an initializer.

I’m confused: isn’t the point of a failable initializer that I can bail out without setting it up if something goes wrong? The object returned would be nil, why would there be any value in setting up its properties?


Solution

  • Failable Initializers for Classes:

    "For classes, however, a failable initializer can trigger an initialization failure only after all stored properties introduced by that class have been set to an initial value and any initializer delegation has taken place."

    So

    init?(json: JSON) {
        self.id = json["id"].string
        self.sortOrder = json["sortOrder"].int
        ...
        if ... { return nil }
    }