ios - 如何在 Swift 中进行异步 api 调用
问题描述
我正在尝试进行 api 调用并在 UICollectionView cellForItemAt 函数中打印结果,但 UICollectionView 在从 api 获取数据时滞后。我尝试了集合视图预取 api,但我无法实现它。如何解决滞后滚动问题? 这是问题所在:
这是我的 api 调用类:
class ApiManager {
static var url: String?
static var header: [String : String]?
static var httpMethod: String?
static let session = URLSession.shared
static func getTask(itemName: String, completion:@escaping ([String]) -> Void) -> URLSessionDataTask {
let url = URL(string: ApiManager.url!)
var request = URLRequest(url: url!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.allHTTPHeaderFields = ApiManager.header!
request.httpMethod = ApiManager.httpMethod
let session = ApiManager.session
let dataTask = session.dataTask(with: request) { data, response, error in
if error == nil && data != nil {
if (error != nil) {
print(error!)
} else {
do {
if let dictionary = try JSONSerialization.jsonObject(with: data!, options: []) as? [[String:Any]] {
var itemArray = [String]()
for index in 0...dictionary.count - 1 {
if let items = dictionary[index][itemName] as? String {
itemArray.append(items)
}
}
completion(itemArray)
}
} catch {
}
}
}
}
return dataTask
}
}
这是我的 ViewController 代码:
class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
var quoteArray = [String]()
var categories = ["love", "motivational", "mothersday", "all"]
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
for category in categories {
ApiManager.url = "https://famous-quotes4.p.rapidapi.com/random?category=\(category)&count=1000"
}
ApiManager.header = ["x-rapidapi-host": "famous-quotes4.p.rapidapi.com", "x-rapidapi-key": "SECRET_API_KEY" ]
ApiManager.httpMethod = "GET"
ApiManager.getTask(itemName: "text") { items in
DispatchQueue.main.async {
self.quoteArray.append(contentsOf: items)
self.collectionView.reloadData()
}
}.resume()
}
}
这是我的 cellForItemAt 函数代码:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? Cell else { fatalError("cell dequeue error") }
cell.label.text = self.quoteArray[indexPath.row]
return cell
}
解决方案
推荐阅读
- r - 如何在泊松回归中组合组来估计对比度?
- django - Django:唯一的 id 生成器
- c# - “直接从项目中引用包来解决这个问题。”
- ag-grid - 类“ToolPanelComp”错误地实现了接口“IToolPanel”。“ToolPanelComp”类型中缺少属性“init”
- c++ - opencv c++ 打不开摄像头
- vba - VBA Outlook 附件发布到 URL
- django - 没有外键的模型的 Django formset
- c# - 如何在 async-Main 的入口线程上恢复?
- javascript - 在我的反应应用程序上使用 selected.js
- ruby-on-rails - 在字段验证错误中添加 URL 而不会使模型复杂化