Swift - 在viewDidLoad()中完成http请求之前查看加载

时间:2017-07-02 11:53:11

标签: ios swift multithreading uitableview http

我正在尝试从数据库加载一个值,并将它们放入我的一个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请求列表已添加。我感谢任何帮助!

3 个答案:

答案 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块。