我有一個服務類,它進行 api 呼叫并將資料存盤到其屬性中。然后我的互動器類有一個方法,我想在其中進行服務類 api 呼叫以及何時存盤資料 - 回傳它。我試圖用完成處理程式和調度組來處理這個問題,但是(我想我只是遺漏了一些東西)這不起作用。如果您能幫我解決這個問題,我將不勝感激。提前致謝!
服務等級:
class PunkApiService{
var beers = [Beer]()
func loadList(at page: Int){
//MARK: - Checks is URL is valid pagination
guard let url = URL(string: "https://api.punkapi.com/v2/beers?page=\(page)&per_page=25") else {
print("Invalid URL")
return
}
//MARK: - Creating URLSession DataTask
let task = URLSession.shared.dataTask(with: url){ data, response, error in
//MARK: - Handling no erros came
guard error == nil else {
print(error!)
return
}
//MARK: - Handling data came
guard let data = data else{
print("Failed to load data")
return
}
do{
let beers = try JSONDecoder().decode([Beer].self, from: data)
self.beers.append(contentsOf: beers)
}
catch{
print("Failed to decode data")
}
}
task.resume()
}
和互動器類(沒有完成處理程式或調度組):
class BeersListInteractor:BeersListInteractorProtocol{
private var favoriteBeers = FavoriteBeers()
private var service = PunkApiService()
//MARK: - Load list of Beers
func loadList(at page: Int) -> [Beer]{
service.loadList(at: page)
return service.beers
}
補充:我對完成處理程式的嘗試
var beers: [Beer]
func loadList(at page: Int, completion: ()->()){
service.loadList(at: page)
completion()
}
func completion(){
beers.append(contentsOf: service.beers)
}
loadList(at: 1) {
completion()
}
uj5u.com熱心網友回復:
我認為您在嘗試使用完成塊時走在正確的道路上,只是沒有正確使用。
func loadList(at page: Int, completion: @escaping ((Error?, Bool, [Beer]?) -> Void)) {
//MARK: - Checks is URL is valid pagination
guard let url = URL(string: "https://api.punkapi.com/v2/beers?page=\(page)&per_page=25") else {
print("Invalid URL")
completion(nil, false, nil)
return
}
//MARK: - Creating URLSession DataTask
let task = URLSession.shared.dataTask(with: url){ data, response, error in
//MARK: - Handling no erros came
if let error = error {
completion(error, false, nil)
print(error!)
return
}
//MARK: - Handling data came
guard let data = data, let beers = try? JSONDecoder().decode([Beer].self, from: data) else {
completion(nil, false, nil)
return
}
completion(nil, true, beers)
}
task.resume()
}
這是loadList函式,它現在有一個completion引數,該引數將具有三個引數,分別是 optional Error,Bool表示獲取資料成功或失敗的值,以及[Beers]包含資料(如果已檢索到)的實際陣列。
以下是您現在呼叫該函式的方式:
service.loadList(at: page) { error, success, beers in
if let error = error {
// Handle the error here
return
}
if success, let beers = beers {
// Data was correctly retrieved - and safely unwrapped for good measure, do what you need with it
// Example:
loader.stopLoading()
self.datasource = beers
self.tableView.reloadData()
}
}
請記住,完成是異步執行的,不會停止應用程式其余部分的執行。此外,您應該決定是直接在loadList函式內部還是在閉包內部處理錯誤,Error如果您在函式內部處理它,則可能洗掉引數。其他引數也是如此:您可以決定只擁有一個只有一個[Beer]引數的閉包,并且只有在正確檢索和轉換資料時才呼叫該閉包。
uj5u.com熱心網友回復:
這就是async/await模式的用途,描述為here。在您的情況下,兩個loadList函式都是async,第二個await是第一個:
class PunkApiService {
func loadList(at page: Int) async {
// change function to await for task result
let (data, error) = try await URLSession.shared.data(from: url)
let beers = try JSONDecoder().decode([Beer].self, from: data)
...
return beers
}
}
class BeersListInteractor: BeersListInteractorProtocol {
func loadList(at page: Int) async -> [Beer]{
let beers = await service.loadList(at: page)
return service.beers
}
}
在這里看到一個很好的解釋
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/384081.html
