#ios #swift #api #rest #concurrency
#iOS #быстрый #API #остальное #совпадение
Вопрос:
Я пытаюсь объединить три результата API JSON от трех одновременных вызовов в единую структуру данных (например, CombinedDataStructure), которая будет передана в мой TableView по протоколу делегирования. Я знаю, как отправлять результаты из этих API независимо друг от друга, каждый через свою собственную функцию протокола, но я хотел бы обновлять представление таблицы только тогда, когда все полученные данные доступны не по одному. Я застрял на объединении результатов закрытия API в структуру данных. Независимо от того, что я пытаюсь, я не могу извлечь и объединить значения из замыканий в один тип данных
API1 (два других аналогичны):
func getPrice (completion: @escaping (String) -gt; ()) { let urlString = "https://myApi.com/api/ticker/price?symbol=xxxx" var testReturnString = "No value" // //Make API call if let url = URL(string: urlString){ let session = URLSession(configuration: .default) let task = session.dataTask(with: url) { data, response, error in if error != nil { print(error as Any) } if let safeData = data { let decoder = JSONDecoder() do { let decodedData = try decoder.decode(PriceData.self, from: safeData) testReturnString = decodedData.price print("Inside getPrice Closure:(testReturnString)") //-gt; Here we see correct data from server //testStructStr = decodedData.price -gt; Struct variable assignment - Forces the API to becomes mutating and throws "Cannot use mutating member on immutable value: 'self' is immutable" completion(testReturnString) } catch { print(error) } } } task.resume() print("Outside Closure:(testReturnString)") //-gt; Here we see "No Value" } }
Часть параллелизма выполняется в updateBalanceTable, которая вызывается в viewDidLoad :
func updateBalanceTable(){ let radQueue = OperationQueue() var testStrUpdate = "No Value 2" let operation1 = BlockOperation { let group = DispatchGroup() //API1 group.enter() getCoinPrice { myStr in print("Inside updateBalanceTable closure:(myStr)") testStrUpdate = myStr } group.leave() //API2 group.enter() //getExchangeInfo() - not expanded with closures yet group.leave() //API3 group.enter() //getAllBalances() - not expanded with closures yet group.leave() group.wait() //this operation won't return until we have all data print("Test StrUpdate inside Wait OP1:(testStrUpdate)") } let operation2 = BlockOperation { print("Test StrUpdate inside OP2:(testStrUpdate)") // Now, operation2 will fire off once operation1 has completed, with results wanted } operation2.addDependency(operation1) radQueue.addOperation(operation1) radQueue.addOperation(operation2) }
All these functions are defined inside a struct called BalanceManager:
struct BalanceManager{ var delegate: BalanceProtocol? var testStructStr = "" //I have tried updating a string from Struct directly but I get other errors doing so func getPrice (completion: @escaping (String) -gt; ()) { ... } func getExchangeInfo(completion: @escaping ([Pairs]) -gt; ()) { ... } func getAllBalances(completion: @escaping ([Assets]) -gt; ()) { ... } func updateBalanceTable() { ... } }
Результаты консоли:
Outside Closure: No value Test StrUpdate inside Wait OP1: No Value 2 Test StrUpdate inside OP2: No Value 2 Inside getPrice Closure: 1234.45 Inside updateBalanceTable closure: 1234.45