DispatchQueue 不更新 swift 中的数据
DispatchQueue does not update the data in swift
我需要在 Swift 中执行搜索操作,我使用 UISearchbar 进行搜索。
在 textDidChange 事件中,我需要调用网络 api,解析响应,然后更新数组,然后开始搜索更新后的数组。
但不确定我的代码是否有效。
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({[=11=].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()
}
}
请指导我上面的代码,因为我不确定我哪里错了
问题是 callWebAPI
是异步的(它 returns 紧接在请求完成之前),因此您立即调用 leave
。您可以为该方法提供一个完成处理程序并在其中调用 leave
。您还可以在 notify
块中为您的组调用 UI 更新,而不仅仅是发送它。
更简单,只需完全退出 DispatchGroup
并在您提供给 callWebAPI
的完成处理程序中更新 UI。
例如,给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()
}
}
然后,你可以去掉dispatch groups,global queues(因为已经是异步方法,不需要在后台queue中调用)等等,简化为:
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({[=11=].name.prefix(searchText.count) == searchText})
self.searching = true
self.tableView.reloadData()
}
}
}
顺便说一句,现在我们使用JSONDecoder
解析JSON直接填充模型对象,但这超出了这个问题的范围。
我需要在 Swift 中执行搜索操作,我使用 UISearchbar 进行搜索。
在 textDidChange 事件中,我需要调用网络 api,解析响应,然后更新数组,然后开始搜索更新后的数组。
但不确定我的代码是否有效。
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({[=11=].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()
}
}
请指导我上面的代码,因为我不确定我哪里错了
问题是 callWebAPI
是异步的(它 returns 紧接在请求完成之前),因此您立即调用 leave
。您可以为该方法提供一个完成处理程序并在其中调用 leave
。您还可以在 notify
块中为您的组调用 UI 更新,而不仅仅是发送它。
更简单,只需完全退出 DispatchGroup
并在您提供给 callWebAPI
的完成处理程序中更新 UI。
例如,给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()
}
}
然后,你可以去掉dispatch groups,global queues(因为已经是异步方法,不需要在后台queue中调用)等等,简化为:
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({[=11=].name.prefix(searchText.count) == searchText})
self.searching = true
self.tableView.reloadData()
}
}
}
顺便说一句,现在我们使用JSONDecoder
解析JSON直接填充模型对象,但这超出了这个问题的范围。