0

I previously had problem with the JSON data but found a solution to it as suggested by alexcurylo in the link down below;

Ambiguous use of 'subscript' with NSArray & JSON

It was working fine for a while but now it is returning fatal error: unexpectedly found nil while unwrapping an Optional value on the following line: for video in (JSON as! NSDictionary)["items"] as! NSArray {. Any suggestion on this? I thought that might be related to thumbnails not having maxres but changing it default or high didn't work either.

    let API_KEY = "BrowserKey"


    let UPLOADS_PLAYLIST_ID = "playlistID"


    var videoArray = [Video]()


    var delegate: VideoModelDelegate?


    func getFeedVideos() {

//Fetch the videos dynamically through the Youtube DATA API
Alamofire.request(.GET, "https://www.googleapis.com/youtube/v3/playlists", parameters: ["part":"snippet", "playlistId":UPLOADS_PLAYLIST_ID,"key":API_KEY], encoding: ParameterEncoding.URL, headers: nil).responseJSON { (response) -> Void in


if let JSON = response.result.value {

    var arrayOfVideos = [Video]()


    for video in (JSON as! NSDictionary)["items"] as! NSArray {


        // create video objects off of the JSON response

        let videoObj = Video()
        videoObj.videoId = video.valueForKeyPath("snippet.resourceId.videoId") as! String
        videoObj.videoTitle = video.valueForKeyPath("snippet.title") as! String
        videoObj.videoDescription = video.valueForKeyPath("snippet.description") as! String
        videoObj.videoThumbnailUrl = video.valueForKeyPath("snippet.thumbnails.default.url") as! String


        arrayOfVideos.append(videoObj)

    }

    //when all the video objects constructed, assign the array to the VideoModel property
    self.videoArray = arrayOfVideos

    //Notify the delegate that the data is ready

    if self.delegate != nil {
        self.delegate?.dataReady()
    }

}

}

Community
  • 1
  • 1
  • Either (a) the `JSON` was not a dictionary; (b) it couldn't find anything with the key `items`; or (c) it did find something, but it wasn't an array. You have to test for these situations, one by one, (e.g. with `guard`) and see which doesn't hold. – Rob Jun 01 '16 at 16:55
  • I just made [this](https://github.com/romainmenke/Jenerator) for exactly these kind of issues. It takes a lot of time to map JSON responses and this cli will create a swift model from a JSON for you. Maybe it helps. – R Menke Jun 01 '16 at 18:53

1 Answers1

0

This is why you don't abuse the force unwrap operator (!) like this.

In expression (JSON as! NSDictionary)["items"] as! NSArray:

  1. You are forcefully casting JSON to NSDictionary. If JSON isn't an NSDictionary or a subclass of it, this forced cast will fail and cause a crash.
  2. You are subscripting to get the value for the key "items". This could return nil, if there's no mapping for "items"
  3. You are forcefully casting that value to NSArray. If the value is nil, this will crash. If the value isn't an NSArray or one of its subclasses, this will crash.

The ! should be using sparingly. It creates an assertion that whatever it's unwrapping/casting is valid. As there's no "backup" plan, such as in the case of and if let / else statement, the program crashes. This is an intentional design choice, to prevent the program from continueing to execute in an inconcistent, unforeseen state.

You should use if let and guard to safely handle this data, and react to errors.

Alexander
  • 59,041
  • 12
  • 98
  • 151
  • Forcing it NSDictionary was part of the problem, so I have changed it to -->> for video in (JSON["items"] as? NSArray)! --<<. I have also checked if the videoId, thumbnails and other details are available or not. Thanks! – Burak Pusat Jun 09 '16 at 14:13
  • What was the right answer... I am having the same problem – user3707644 Nov 17 '16 at 10:09