问题
I have a function that returns parsed information out of a JSON string.
var info = [AppModel]()
func getEarthquakeInfo(completion: (results : NSArray?) ->Void ){
DataManager.getEarthquakeDataFromFileWithSuccess {
(data) -> Void in
let json = JSON(data: data)
if let JsonArray = json.array {
for appDict in JsonArray {
var ids: String? = appDict["id"].stringValue
var title: String? = appDict["title"].stringValue
var time: String? = appDict["time"].stringValue
var information = AppModel(idEarth: ids, title: title, time: time)
self.info.append(information)
completion(results: self.info)
}
}
}
}
This function uses SwiftyJSON and calls the web service using my DataManager class. When I print it out outside the function I get all the information I need. Now I want to use the title information to populate my TableView. Inside my cellForRowAtIndexPath I've tried filtering out my Earthinformation so that I could get just the title and put that into an array, and populate my tableView with that array. So far I've been unsuccessful, and I've been looking everywhere on how to do this and nothing I've tried or found worked. Can someone point me in the right direction on how to do this? What I've done so far:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as UITableViewCell
getEarthquakeInfo( { (info) -> Void in
var Earthinformation = self.info as NSArray
let titleArray = Earthinformation["TITLE"] as NSArray // error: type int does not conform to protocol "StringLiteralConvertible"
cell.textLabel!.text = titleArray[indexPath.row]
})
return cell
}
3 records I get when I print out Earthinformation I get: ID: 146323, TITLE: M 1.6 - 27km E of Coso Junction, California, TIME: 2015-04-15 14:08:20 UTC, , ID: 146346, TITLE: M 1.8 - 26km E of Coso Junction, California, TIME: 2015-04-15 14:08:20 UTC, , ID: 146324, TITLE: M 2.4 - 26km NW of Anchor Point, Alaska, TIME: 2015-04-15 13:33:36 UTC,
Edit: Sorry I should have included this before: My AppModel.swift:
class AppModel: NSObject, Printable {
let idEarth: String
let title: String
let time: String
override var description: String {
return "ID: \(idEarth), TITLE: \(title), TIME: \(time), \n"
}
init(idEarth: String?, title: String?, time: String?) {
self.idEarth = idEarth ?? ""
self.title = title ?? ""
self.time = time ?? ""
}
}
And my DataManager.swift file:
let earthquakeURL = "http://www.kuakes.com/json/"
class DataManager {
class func getEarthquakeDataFromFileWithSuccess(success: ((websiteData: NSData) -> Void)) {
//1
loadDataFromURL(NSURL(string: earthquakeURL)!, completion:{(data, error) -> Void in
//2
if let urlData = data {
//3
success(websiteData: urlData)
}
})
}
class func loadDataFromURL(url: NSURL, completion:(data: NSData?, error: NSError?) -> Void) {
var session = NSURLSession.sharedSession()
// Use NSURLSession to get data from an NSURL
let loadDataTask = session.dataTaskWithURL(url, completionHandler: { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
if let responseError = error {
completion(data: nil, error: responseError)
} else if let httpResponse = response as? NSHTTPURLResponse {
if httpResponse.statusCode != 200 {
var statusError = NSError(domain:"com.kuakes", code:httpResponse.statusCode, userInfo:[NSLocalizedDescriptionKey : "HTTP status code has unexpected value."])
completion(data: nil, error: statusError)
} else {
completion(data: data, error: nil)
}
}
})
loadDataTask.resume()
}
}
回答1:
You are calling your getEarthquakeInfo
function every time a cell is to be created. This is very unnecessary and may cause unintentional behavior (seeing as the getEarthquakeInfo
function is asynchronous). I recommend utilizing the fact that you have a model array info already to use to populate your tableview. In viewDidLoad call your asynchronous function to retrieve the data for the model array. Example:
override func viewDidLoad() {
super.viewDidLoad()
getEarthquakeInfo { (info) in
// Your model array is now populated so we should reload our data
self.tableView.reloadData()
}
}
Now, adjust your UITableViewDataSource
functions to properly handle the model array. Note that I am assuming that your info
array is a property of the UITableViewController
that is populating the tableView. Example:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier",
forIndexPath: indexPath) as UITableViewCell
// Note that I have no idea how you access the title of your AppModel
// object so you may have to adjust the below code
cell.textLabel!.text = self.info[indexPath.row].title
return cell
}
override func numberOfSectionsInTableView() {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) {
return info.count
}
来源:https://stackoverflow.com/questions/29663965/populating-tableview-with-a-function-that-uses-swiftyjson