i'm trying parse data data source, titles parsed correctly , displayed, problem occurred when parsing images, got error: “fatal error: unexpectedly found nil while unwrapping optional value” here code:
viewmodel.swift
import foundation class viewmodel { let urlstring = "http://ax.itunes.apple.com/webobjects/mzstoreservices.woa/ws/rss/topsongs/limit=30/json" var titles = [string]() var images = [string]() func fetchtitles(success:() -> ()) { let session = nsurlsession(configuration: nsurlsessionconfiguration.defaultsessionconfiguration()) let url = nsurl(string: urlstring) let task = session.datataskwithurl(url!) { (data, response, error) -> void in let parser = jsonparser() self.titles = parser.titlesfromjson(data!) success() } task.resume() } func fetchimages(success:() -> ()) { let session = nsurlsession(configuration: nsurlsessionconfiguration.defaultsessionconfiguration()) let url = nsurl(string: urlstring) let task = session.datataskwithurl(url!) { (data, response, error) -> void in let parser = jsonparser() self.images = parser.imagesfromjson(data!) success() } task.resume() } func numberofsections() -> int { return 1 } func numberofitemsinsection(section: int) -> int { return titles.count } func titleforitematindexpath(indexpath: nsindexpath) -> string { return titles[indexpath.row] } }
and mytableviewcontroller.swift
import uikit class mytableviewcontroller: uitableviewcontroller { let viewmodel = viewmodel() var imagecache = [string:uiimage]() override func viewdidload() { super.viewdidload() self.refresh() self.refreshcontrol = uirefreshcontrol() self.refreshcontrol?.addtarget(self, action: #selector(mytableviewcontroller.refresh), forcontrolevents: .valuechanged) } func refresh() { viewmodel.fetchtitles { dispatch_async(dispatch_get_main_queue()) { self.tableview.reloaddata() self.refreshcontrol?.endrefreshing() } } viewmodel.fetchimages { dispatch_async(dispatch_get_main_queue()) { self.tableview.reloaddata() self.refreshcontrol?.endrefreshing() } } } override func numberofsectionsintableview(tableview: uitableview) -> int { return self.viewmodel.numberofsections() } override func tableview(tableview: uitableview, numberofrowsinsection section: int) -> int { return self.viewmodel.numberofitemsinsection(section) } override func tableview(tableview: uitableview, cellforrowatindexpath indexpath: nsindexpath) -> uitableviewcell { let cell = tableview.dequeuereusablecellwithidentifier("cell", forindexpath: indexpath) as! mytableviewcell cell.songtitle.text = self.viewmodel.titleforitematindexpath(indexpath) let urlstring = self.viewmodel.titleforitematindexpath(indexpath) //found nil let imgurl: nsurl = nsurl(string: urlstring)! let request: nsurlrequest = nsurlrequest(url: imgurl) nsurlconnection.sendasynchronousrequest( request, queue: nsoperationqueue.mainqueue(), completionhandler: {(response: nsurlresponse?, data: nsdata?, error: nserror?) -> void in if error == nil { cell.songimage.image = uiimage(data: data!) } }) return cell }
and jsonparser.swift
import foundation class jsonparser { func titlesfromjson(data: nsdata) -> [string] { var titles = [string]() { if let json = try nsjsonserialization.jsonobjectwithdata(data, options: []) as? [string: anyobject], let feed = json["feed"] as? [string: anyobject], entries = feed["entry"] as? [[string: anyobject]] { entry in entries { if let name = entry["im:name"] as? [string: anyobject], label = name["label"] as? string { titles.append(label) } } } } catch { print("error parsing json: \(error)") } return titles } func imagesfromjson(data: nsdata) -> [string] { var images = [string]() { if let json = try nsjsonserialization.jsonobjectwithdata(data, options: []) as? [string: anyobject], let feed = json["feed"] as? [string: anyobject], entries = feed["entry"] as? [[string: anyobject]] { entry in entries { if let name = entry["im:image"]![0] as? [string: anyobject], label = name["label"] as? string { images.append(label) } } } } catch { print("error parsing json: \(error)") } return images } }
and have class mytableviewcell subclass of uitableviewcell containing uilabel , uiimageview. can't figure out what's problem, , why i'm getting error. thank time.
i recommend avoid use of force-unwrapping , adopt more secure way of code (e.g using optional binding) avoiding runtime errors. can change code following code , avoid runtime error:
for entry in entries { if let name = entry["im:image"], let value = name[0] as? [string: anyobject], label = value["label"] as? string { images.append(label) } }
in above way avoid use of force-unwrapping.
i hope you.