Mar*_*ers -1 parsing json tableview ios swift
我在自定义类中有一个异步方法,它返回一个包含字典的NSArray.我试图在UITableView中显示这些数据.一个问题是getGenres方法调用是异步的,因此在显示表之后会加载数据.主要问题是弄清楚如何实现3种数据源方法.在Objective C中,这很简单......
var genreList:NSArray?
override func viewDidLoad() {
super.viewDidLoad()
Bookshop.getGenres {
genres in
self.genreList = genres // copies data to the public NSArray
self.tableView.reloadData() // this returns the data async so need to reload the tableview
println("records: \(self.genreList?.count)") // displays the array of dictionaries correctly
}
}
// #pragma mark - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
return 1
}
override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
if self.genreList != nil {
println("Rows in section: \(self.genreList?.objectAtIndex(0))")
return self.genreList?.count! // Value of optional 'Int?' not wrapped; did you mean to use '!'
}
return 3
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell? {
let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("GenreCell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel.text = "Hello World!"
println("ROW: \(indexPath.row)")
println("data: \(self.genreList?.objectAtIndex(indexPath.row))")
var item = self.genreList?.objectAtIndex(indexPath.row) Variable 'item' inferred to have type 'AnyObject?', which may be unexpected.
//cell.textLabel.text = item.title
//var item:NSDictionary = self.genreList?.objectAtIndex(indexPath.row) as NSDictionary
//println("item: \(item)")
return cell
}
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?做一个非常简单的任务似乎是不必要的复杂.
这是我的实用程序类:
import Foundation
class Bookshop {
class func getGenres(completionHandler: (genres: NSArray) -> ()) {
//println("Hello inside getGenres")
let urlPath = "http://creative.coventry.ac.uk/~bookshop/v1.1/index.php/genre/list"
//println(urlPath)
let url: NSURL = NSURL(string: urlPath)
let session = NSURLSession.sharedSession()
var resultsArray:NSArray!
let task = session.dataTaskWithURL(url) {
data, response, error in
//println("Task completed")
if(error) {
println(error.localizedDescription)
}
//println("no error")
var err: NSError?
var options:NSJSONReadingOptions = NSJSONReadingOptions.MutableContainers
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: options, error: &err) as NSDictionary
if(err != nil) {
println("JSON Error \(err!.localizedDescription)")
}
//NSLog("jsonResults %@", jsonResult)
let results: NSArray = jsonResult["genres"] as NSArray
//NSLog("jsonResults %@", results)
//resultsArray = results
//println("calling completion handler")
completionHandler(genres: results)
}
task.resume()
}
}
Run Code Online (Sandbox Code Playgroud)
快速做的只是消除了一堆我们真的不应该依赖的容易出错的功能,特别是依赖于设置为零的消息总是容易出错.现在它有点冗长,但更明确,因此更安全.
return self.genreList.count在Objective-C中的等价物是:
override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
if let genres = self.genreList {
return genres.count
}
else {
// Note: this is the case when you haven't yet downloaded your genre
// list, do whatever is appropriate, this just shows an empty list
return 0
}
}
Run Code Online (Sandbox Code Playgroud)
由于cellForRowAtIndexPath只有在非零单元数的情况下才会调用,因此该方法更简单,但实际上为了一致性/安全性,您遵循相同的一般流程:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell? {
if let genres = self.genreList as? [NSDictionary] {
let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("GenreCell", forIndexPath: indexPath) as UITableViewCell
var item = genres[indexPath.row]
cell.textLabel.text = item["title"] as String
return cell
}
else {
// Note: again, this is the case where you don't have your genre list
// list yet, so you can create whatever default cells needed.
return nil
}
}
Run Code Online (Sandbox Code Playgroud)