Search code examples
iosjsonswiftfoursquarensurlsession

Swift: If let statement failing to handle empty array


I have an application that is using the Foursquare API to download JSON data. I am using NSURLSession and the dataTaskWithRequest with completion block method to fetch the data. I am getting the data fine but sometimes a nested array named groups can be empty. And when I am parsing through the JSON like below, for some reason my conditional statement is not handling the empty array like I am expecting it should. Instead of evaluating the array as empty and proceeding to the "else" portion of the if let...else statement if instead throughs a runtime error stating: index 0 beyond bounds of empty array

if let response: NSDictionary = data["response"] as? [String: AnyObject],
            groups: NSArray = response["groups"] as? NSArray,
                        // Error here \|/ (sometimes groups array is empty)
            dic: NSDictionary = groups[0] as? NSDictionary,
            items: NSArray = dic["items"] as! NSArray {

}

else {

    // Never gets here. Why?
    // IF the groups array is empty, then the if let should return 
    // false and drop down to the else block, right?
}

I am relatively new to Swift, can someone tell me why this is happening and what I can do to fix this? Thanks


Solution

  • You have to check explicitly outside an if letstatement if the array is empty, because

    An empty array is never an optional

    if let response = data["response"] as? [String: AnyObject], groups = response["groups"] as? NSArray {
      if !groups.isEmpty {
        if let dic = groups[0] as? NSDictionary {
           items = dic["items"] as! NSArray
           // do something with items
           println(items)
        }
      }
    } else ...
    

    You can omit all type annotations while downcasting a type

    However, you can perform the check with a where clause, this works in Swift 1.2 and 2

    if let response = data["response"] as? [String: AnyObject],
                      groups = response["groups"] as? [AnyObject] where !groups.isEmpty,
                      let dic = groups[0] as? NSDictionary,
                      items = dic["items"] as? NSArray {
       // do something with items
       println(items)
    } else {...