我正在尝试从数据库加载一个值,并将它们放入我的一个Swift文件的viewDidLoad函数中的UITableView中。在调试时,在视图呈现时,值列表为空,但在加载视图后,列表将由视图加载填充。我对Swift中的线程没有多少经验,所以我不确定为什么会发生这种情况,任何想法?我曾尝试运行DispatchQueue.main.async,但这不起作用我的代码如下:
override func viewDidLoad() {
super.viewDidLoad()
// Load any saved meals, otherwise load sample data.
loadDbMeals()
}
private func loadDbMeals() {
var dbMeals = [Meal]()
let requestURL = NSURL(string: self.URL_GET)
let request = NSMutableURLRequest(url: requestURL! as URL)
request.httpMethod = "GET"
//creating a task to send the post request
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
if error != nil{
print("error is \(String(describing: error))")
return;
}
//parsing the response
do {
//converting response to NSDictionary
let myJSON = try JSONSerialization.jsonObject(with: data!, options: [.mutableContainers]) as? NSDictionary
//parsing the json
if let parseJSON = myJSON {
if let nestedDictionary = parseJSON["message"] as? NSArray {
for meal in nestedDictionary {
if let nestedMeal = meal as? NSDictionary {
let mealName = nestedMeal["name"]
let rating = nestedMeal["rating"]
dbMeals.append(Meal(name: mealName as! String, photo: UIImage(named: "defaultPhoto"), rating: rating as! Int, ingredientList: [])!)
}
}
}
}
} catch {
print(error)
}
}
meals += dbMeals
//executing the task
task.resume()
}
因此,断点的当前顺序是在viewDidLoad()函数中调用loadDbMeals(),然后它尝试将dbMeals变量添加到全局meal变量中,然后在空后执行http请求列表已添加。我感谢任何帮助!
答案 0 :(得分:2)
加载数据后重新加载表
if let parseJSON = myJSON {
if let nestedDictionary = parseJSON["message"] as? NSArray {
for meal in nestedDictionary {
if let nestedMeal = meal as? NSDictionary {
let mealName = nestedMeal["name"]
let rating = nestedMeal["rating"]
dbMeals.append(Meal(name: mealName as! String, photo: UIImage(named: "defaultPhoto"), rating: rating as! Int, ingredientList: [])!)
}
}
DispatchQueue.main.async{
self.tableView.reloadData()
}
}
}
答案 1 :(得分:0)
请求异步发生。因此在请求可能仍在进行时加载视图。
将meals += dbMeals
行移动到请求的完成处理程序中(在for
循环之后),将self.
添加到膳食变量中,因为您正在引用它之后关闭并从主线程重新加载tableview:
DispatchQueue.main.async{
self.tableView.reloadData()
}
答案 2 :(得分:0)
因为dataTask
不是同步调用,所以我们需要使用lock来等待所有提取完成。
代码看起来像这样:
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.global().async {
let lock = DispatchSemaphore(value: 0)
// Load any saved meals, otherwise load sample data.
self.loadDbMeals(completion: {
lock.signal()
})
lock.wait()
// finished fetching data
}
}
private func loadDbMeals(completion: (() -> Void)?) {
var dbMeals = [Meal]()
let requestURL = NSURL(string: self.URL_GET)
let request = NSMutableURLRequest(url: requestURL! as URL)
request.httpMethod = "GET"
//creating a task to send the post request
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
if error != nil{
print("error is \(String(describing: error))")
return;
}
//parsing the response
do {
//converting response to NSDictionary
let myJSON = try JSONSerialization.jsonObject(with: data!, options: [.mutableContainers]) as? NSDictionary
//parsing the json
if let parseJSON = myJSON {
if let nestedDictionary = parseJSON["message"] as? NSArray {
for meal in nestedDictionary {
if let nestedMeal = meal as? NSDictionary {
let mealName = nestedMeal["name"]
let rating = nestedMeal["rating"]
dbMeals.append(Meal(name: mealName as! String, photo: UIImage(named: "defaultPhoto"), rating: rating as! Int, ingredientList: [])!)
}
}
}
}
} catch {
print(error)
}
// call completion
completion()
}
meals += dbMeals
//executing the task
task.resume()
}
因此执行带有完成块的loadDbMeals
将在获取完成时调用,锁将等到调用completion
块。