简体   繁体   English

DispatchQueue不会快速更新数据

[英]DispatchQueue does not update the data in swift

I'm need to do a search operation in Swift and me using UISearchbar for it. 我需要在Swift中进行搜索操作,并使用UISearchbar进行搜索。

On textDidChange event, I need to call a web api, parse the response and then update the array and then begin the search on updated array. 在textDidChange事件上,我需要调用网络api,解析响应,然后更新数组,然后开始对更新后的数组进行搜索。

But not sure my code does not work. 但不确定我的代码是否起作用。

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

    let group = DispatchGroup()
    group.enter()
    // Perform some asynchronous operation
    let queue1 = DispatchQueue(label: "abc")
    queue1.async {
        self.callWebAPI() // This function calls the web api and parses it’s response
        group.leave()
    }

    DispatchQueue.global(qos: .utility).async {
        DispatchQueue.main.async {
            self.filteredCountry = self.arrCountry.filter({$0.name.prefix(searchText.count) == searchText})
            self.searching = true
            self.tableView.reloadData()
        }
    }
}

func callWebAPI() {
    let urlString = URL(string: "https://restcountries.eu/rest/v2/all")
    if let url = urlString {
        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            if error != nil {
                print(error!)
            } else {
                if let usableData = data {
                    do{
                        //here dataResponse received from a network request
                        let jsonResponse = try JSONSerialization.jsonObject(with:
                            data!, options: [])
                        print(jsonResponse) //Response result

                        guard let jsonArray = jsonResponse as? [[String: Any]] else {
                            return
                        }


                        print(jsonArray)

                        print("done")

                    } catch let parsingError {
                        print("Error", parsingError)
                    }

                }
            }
        }
        task.resume()
    }

}

Please guide on my above code as not sure where I'm wrong 请指导我上面的代码,以免我错了

The issue is that callWebAPI is asynchronous (it returns immediately before the request is done), so you are calling leave immediately. 问题在于callWebAPI是异步的(它在请求完成之前立即返回),因此您正在立即调用leave You could give this method a completion handler and call leave in that. 您可以为该方法提供完成处理程序,然后在其中调用leave And you would also call the UI update in a notify block for your group, not just dispatch it. 您还可以在组的notify块中调用UI更新,而不仅仅是调度它。

Easier, just retire the DispatchGroup entirely and just update your UI in the completion handler you supply to callWebAPI . 更简单地,只需完全淘汰DispatchGroup并在提供给callWebAPI的完成处理程序中更新UI。

For example, give callWebAPI a completion handler: 例如,为callWebAPI提供完成处理程序:

func callWebAPI(completionHandler: @escaping ([[String: Any]]?, Error?) -> Void) {
    let urlString = URL(string: "https://restcountries.eu/rest/v2/all")
    if let url = urlString {
        let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard let data = data, error == nil else {
                completionHandler(nil, error)
                return
            }

            do {
                let jsonResponse = try JSONSerialization.jsonObject(with:
                    data)

                completionHandler(jsonResponse as? [[String: Any]], nil)
            } catch let parsingError {
                completionHandler(nil, parsingError)
            }
        }
        task.resume()
    }
}

And then, you can eliminate the dispatch groups, the global queues (because it's already an asynchronous method, you don't need to invoke this from background queue), etc., and it's simplified to just: 然后,您可以消除调度组,全局队列(因为它已经是一个异步方法,因此不需要从后台队列中调用此方法),等等,并将其简化为:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    callWebAPI { jsonResponse, error in
        guard let jsonResponse = jsonResponse, error == nil else {
            print("Error:", error ?? "Response was not correct format")
            return
        }

        print(jsonResponse)

        // Note, you don’t appear to be using `jsonResponse` at all,
        // so I presume you’d update the relevant model objects.

        DispatchQueue.main.async {
            self.filteredCountry = self.arrCountry.filter({$0.name.prefix(searchText.count) == searchText})
            self.searching = true
            self.tableView.reloadData()
        }
    }
}

As an aside, nowadays we use JSONDecoder to parse JSON to populate model objects directly, but that's beyond the scope of this question. JSONDecoder ,如今我们使用JSONDecoder解析JSON以直接填充模型对象,但这超出了此问题的范围。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM