Я вхожу в URL веб-службы 10 раз и получаю ответ.Я использую Alamofire
и SwiftyJSON
.Это мой код контроллера
class ViewController: UIViewController {
let dispatchGroup = DispatchGroup()
var weatherServiceURL = "http://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22"
override func viewDidLoad() {
super.viewDidLoad()
start()
}
func start() {
weatherService()
dispatchGroup.notify(queue: .main) {
print("All services complete")
}
}
func weatherService() {
for i in 1...10 {
dispatchGroup.enter()
APIManager.apiGet(serviceName: self.weatherServiceURL, parameters: ["counter":i]) { (response:JSON?, error:NSError?, count:Int) in
if let error = error {
print(error.localizedDescription)
return
}
guard let response = response else { return }
print("\n\(response) \n\(count) response\n")
self.dispatchGroup.leave()
}
}
}
}
Это мой код класса Service Handler
class APIManager: NSObject {
class func apiGet(serviceName:String,parameters: [String:Any]?, completionHandler: @escaping (JSON?, NSError?, Int) -> ()) {
Alamofire.request(serviceName, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in
switch(response.result) {
case .success(_):
if let data = response.result.value{
let json = JSON(data)
completionHandler(json,nil, parameters!["counter"] as! Int)
}
break
case .failure(_):
completionHandler(nil,response.result.error as NSError?, parameters!["counter"] as! Int)
break
}
}
}
}
Я отправляю счетчик ключа с индексом цикла for просто для отслеживания ответакакой индекс возвращается.Но ответ идет не в серийном порядке.Мы можем ожидать 3-й ответ до 2-го и 1-го ответа.Это связано с тем, что вызов API с вызовом функции APIManager.apiGet
является асинхронным и экранируется, и поэтому продолжается цикл for.
Также я использовал dispatchQueue
let dispatchQueue = DispatchQueue(label: "com.test.Queue", qos: .userInteractive)
и преобразовал функцию следующим образом:
func weatherService() {
for i in 1...10 {
dispatchGroup.enter()
dispatchQueue.async {
APIManager.apiGet(serviceName: self.weatherServiceURL, parameters: ["counter":i]) { (response:JSON?, error:NSError?, count:Int) in
if let error = error {
print(error.localizedDescription)
return
}
guard let response = response else { return }
print("\n\(response) \n\(count) response\n")
self.dispatchGroup.leave()
}
}
}
}
Тот же результат, что и код вызова службы асинхронный.Если мы сделаем
dispatchQueue.sync {
//service call
}
, то мы также не получим ответ в последовательном порядке, так как сетевой вызов в async и dispatchQueue предполагает, что задача выполнена.
Условием является включение службы втолько в асинхронном режиме без зависания интерфейса.Если я нажму на сервис синхронно, то получу желаемый результат.Но блокировка основного потока совсем не приемлема.
Я могу управлять этим, используя массив или некоторые глобальные переменные bool, но я не хочу их использовать.Есть ли другой способ получить ответ в последовательном порядке, в котором он вызывается?Любая помощь или подсказка приветствуется.