這是對以下問題的跟進:為什么代碼沒有在第二個 URLSession.shared.dataTask 之后/之內執行,即在初始 URLSession.shared.dataTask 的 do 塊內?迅速
我正在嘗試將變數的當前實體分配給self.variable類實體的函式呼叫。
這可以在附加代碼的 ViewController.swift 中以“self.venues =”開頭的代碼行中看到。
我相信Task與此有關。我已經閱讀了關于 的檔案Task,并在網上閱讀了更多關于它的資訊,但還沒有找到解決方案。
另外:我在 ViewController.swift 中以“self.venues =”開頭的代碼行中收到錯誤訊息“無法將型別 'Task<(), Never>' 的值分配給型別 '[Venue]'”。
代碼:
ViewController.swift:
import UIKit
import CoreLocation
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet var tableView: UITableView!
var venues: [Venue] = []
override func viewDidLoad() async {
super.viewDidLoad()
tableView.register(UINib(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "CustomTableViewCell")
tableView.delegate = self
tableView.dataSource = self
let yelpApi = YelpApi(apiKey: "Api key")
self.venues = Task {
do { try await yelpApi.searchBusiness(latitude: selectedLatitude, longitude: selectedLongitude, category: "category quary goes here", sortBy: "sort by quary goes here", openAt: )
}
catch {
//Handle error here.
print("Error")
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return venues.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as! CustomTableViewCell
//Details for custom table view cell go here.
}
//Rest of table view protocol functions.
}
Venue.swift:
import Foundation
// MARK: - BusinessSearchResult
struct BusinessSearchResult: Codable {
let total: Int
let businesses: [Venue]
let region: Region
}
// MARK: - Business
struct Venue: Codable {
let rating: Double
let price, phone, alias: String?
let id: String
let isClosed: Bool?
let categories: [Category]
let reviewCount: Int?
let name: String
let url: String?
let coordinates: Center
let imageURL: String?
let location: Location
let distance: Double
let transactions: [String]
enum CodingKeys: String, CodingKey {
case rating, price, phone, id, alias
case isClosed
case categories
case reviewCount
case name, url, coordinates
case imageURL
case location, distance, transactions
}
}
// MARK: - Category
struct Category: Codable {
let alias, title: String
}
// MARK: - Center
struct Center: Codable {
let latitude, longitude: Double
}
// MARK: - Location
struct Location: Codable {
let city, country, address2, address3: String?
let state, address1, zipCode: String?
enum CodingKeys: String, CodingKey {
case city, country, address2, address3, state, address1
case zipCode
}
}
// MARK: - Region
struct Region: Codable {
let center: Center
}
FetchData.swift:
import UIKit
import Foundation
import CoreLocation
class YelpApi {
private var apiKey: String
init(apiKey: String) {
self.apiKey = apiKey
}
func searchBusiness(latitude: Double,
longitude: Double,
category: String,
sortBy: String) async throws -> [Venue] {
var queryItems = [URLQueryItem]()
queryItems.append(URLQueryItem(name:"latitude",value:"\(latitude)"))
queryItems.append(URLQueryItem(name:"longitude",value:"\(longitude)"))
queryItems.append(URLQueryItem(name:"categories", value:category))
queryItems.append(URLQueryItem(name:"sort_by",value:sortBy))
var results = [Venue]()
var expectedCount = 0
let countLimit = 50
var offset = 0
queryItems.append(URLQueryItem(name:"limit", value:"\(countLimit)"))
repeat {
var offsetQueryItems = queryItems
offsetQueryItems.append(URLQueryItem(name:"offset",value: "\(offset)"))
var urlComponents = URLComponents(string: "https://api.yelp.com/v3/businesses/search")
urlComponents?.queryItems = offsetQueryItems
guard let url = urlComponents?.url else {
throw URLError(.badURL)
}
var request = URLRequest(url: url)
request.setValue("Bearer \(self.apiKey)", forHTTPHeaderField: "Authorization")
let (data, _) = try await URLSession.shared.data(for: request)
let businessResults = try JSONDecoder().decode(BusinessSearchResult.self, from:data)
expectedCount = min(businessResults.total,1000)
results.append(contentsOf: businessResults.businesses)
offset = businessResults.businesses.count
} while (results.count < expectedCount)
return results
}
}
謝謝!
uj5u.com熱心網友回復:
您有一個異步操作 - searchBusinesses. 呼叫此函式時,需要時間才能得到結果。你await用來處理這個。
您不能await在異步背景關系之外使用,事實viewDidLoad并非如此。您正在使用 aTask創建異步背景關系。到目前為止,一切都很好。
你出錯的地方是試圖將結果分配給venues. 您只能在await完成后執行此分配。你沒有從a得到這個結果,Task你得到它:Task
Task {
do {
self.venues = try await yelpApi.searchBusiness(latitude: selectedLatitude, longitude: selectedLongitude, category: "category quary goes here", sortBy: "sort by quary goes here", openAt: )
self.tableView.reloadData()
} catch {
//Handle error here.
print("Error")
}
}
請注意,您不應該將 GCD 調度佇列和 async/await 結合使用,在這種情況下,您無需擔心主佇列。
UIViewController被標記@MainActor。這意味著除非您專門創建分離任務,否則任務已經在主要參與者上執行。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/481291.html
