Search code examples
jsonswiftalamofire

how to check for JSON nil in Swift in a convenience initializer


I have inherited a Swift project from another developer. We are adding an imageUrl that can now be a part of an item which is returned from a JSON api. We are returning the using Alamofire.

One issue is that we can have a null value for our instore_image_url_200w which becomes the item's imageUrl. I guess I have two questions. It would seem like I'd like to have imageUrl be an optional string. Is this correct? If yes, what is the proper way to handle the nil value during initialization? I'd like to be checking for nil on display for item.imageUrl

  var items = [Item]()
  Alamofire.request(URL(string: "https://www.example.com/api/v1/metro_areas/1")!, method: .get).validate().responseJSON { (response) -> Void in
    guard let value = response.result.value as? [String: Any],
      let rows = value["items"] as? [[String: Any]] else {
        print("Malformed data received from fetchAllRooms service")
        return
    }
    for row in rows {
      let item = Item(data: row)
      if (item.imageUrl is String){
        print("here is item.imageUrl: \(item.imageUrl!)")
      }
      items.append(item)

    }
}

and the model:

class Item {
  var name: String
  var imageUrl: String?

  init(name: String, imageUrl: String) {

    self.name = name
    self.imageUrl = imageUrl
  }

  convenience init(data: [String:Any]) {
    let name = data["header"] as? String
    let imageUrl = data["instore_image_url_200w"] as! String?
    self.init(name: name!,
              imageUrl: imageUrl)
  }
}

Solution

  • Yes, the imageUrl would be an optional string since it might, or might not, exist in the JSON data. One point - you currently have your model initializer code for the imageUrl as:

    let imageUrl = data["instore_image_url_200w"] as! String?
    

    Personally, I think it would be cleaner to have it as:

    let imageUrl = data["instore_image_url_200w"] as? String
    

    As for your second question, if you have the initialization as above, the nil value would be automatically handled during initialization since the imageUrl value is optional and so it would either be set to nil (on a nil value) or have an actual string value.

    Of course, when you use imageUrl you'd always have to do a check to see if it is nil or has a value, but you already mentioned that you'd be doing that on display.