我有一个tableView,我想填写一个Web服务提供的项目列表。该服务返回一个状态为(成功或失败)的JSON对象,并显示(一个字符串数组)。
在viewDidLoad中,我调用自定义方法getShowsFromService()
func getShowsFromService() {
// Send user data to server side
let myURL = NSURL(string: "https://myurl.com/srvc/shows.php")
// Create session instance
let session = NSURLSession.sharedSession()
var json:NSDictionary = [:]
// Create the task
let task = session.dataTaskWithURL(myURL!) { //.dataTaskWithRequest(request) {
(data, response, error) in
guard let data = data else {
print("Error: \(error!.code)")
print("\(error!.localizedDescription)")
return
}
do {
json = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions()) as! NSDictionary
} catch {
print (error)
}
let sts = json["status"] as! NSString
print("\(sts)")
}
// Resume the task so it starts
task.resume()
let shows = json["shows"] as! NSArray
for show in shows {
let thisshow = show as! String
showsArray.append(thisshow)
}
// Here I get "fatal error: unexpectedly found nil while unwrapping an Optional value"
}
该方法接收JSON对象并将其放入字典中。然后我想使用该字典调用json ['shows']以获取我想要存储在名为showsArray的实例变量中的节目数组。我们的想法是在tableView(cellForRowAtIndexPath)中使用showsArray来填充数据。
问题是我无法将Dictionary放入变量中。如果我尝试在任务中执行此操作,则会收到一条错误消息,指出我需要调用self.showsArray,如果我这样做,则数据不会进入数组内部。如果我在任务之外执行此操作,则会出现错误,因为它表示我正试图强制解包nil值。
如何将在任务中创建的Dictionary输入到showsArray var?
中答案 0 :(得分:0)
dataTaskWithURL方法进行异步调用,因此只要你执行task.resume(),它就会跳转到下一行,并且json [“shows”]将返回nil,因为此时字典为空。
我建议将该逻辑移到您班级某处的完成处理程序中。有点像:
func getShowsFromService() {
let myURL = NSURL(string: "https://myurl.com/srvc/shows.php")
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(myURL!, completionHandler: handleResult)
task.resume()
}
//-handle your result
func handleResult(data: NSData?, response: NSURLResponse?, error: NSError?) {
guard let data = data else {
print("Error: \(error!.code)")
print("\(error!.localizedDescription)")
return
}
do {
if let json = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions()) as! NSDictionary {
if let shows = json["shows"] as! NSArray {
//- this is still in a separate thread
//- lets go back to the main thread!
dispatch_async(dispatch_get_main_queue(), {
//- this happens in the main thread
for show in shows {
showsArray.append(show as! String)
}
//- When we've got our data ready, reload the table
self.MyTableView.reloadData()
self.refreshControl?.endRefreshing()
});
}
}
} catch {
print (error)
}
}
上面的代码段应该作为指南(我无法访问游乐场atm)。
请注意以下事项: 一旦任务完成(异步 - >不同的线程),它将调用新函数 handleResult ,它将检查错误,如果没有,它将使用调度程序在主线程上执行任务。我假设showsArrays是一个类属性。
我希望这会有所帮助
修改强>
一旦获取数据,您需要重新加载表(上面的更新代码)。您可以使用刷新控件(将其声明为类属性)。
var refreshControl: UIRefreshControl!
然后,当您完成数据后,您可以刷新:
self.MyTableView.reloadData()
self.refreshControl?.endRefreshing()
这将调用您的委托方法来填充行和部分。