这是以下问题的后续:为什么代码不在第二个 URLSession.shared.dataTask 之后/之内执行,即在初始 URLSession.shared.dataTask 的 do 块内?迅速 https://stackoverflow.com/questions/72308605/why-isnt-code-being-executed-after-within-a-second-urlsession-shared-datatask/72329561?noredirect=1#comment127788962_72329561
我正在尝试使用分配变量的当前实例self.variable
从类的实例进行函数调用。
这可以在所附代码中 ViewController.swift 中以“self.venues =”开头的代码行中看到。
我相信Task
与此有关。我读过有关的文档Task
,并在网上阅读了更多相关信息,但尚未找到解决方案。
另外:我在 ViewController.swift 中以“self.venues =”开头的代码行收到错误消息“无法将类型‘Task’的值分配给类型‘[Venue]’”。
Code:
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 query goes here", sortBy: "sort by query 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
}
}
Thanks!