2017-02-09 7 views
1

Я пытаюсь создать свой первый проект со скоростью 3.Синхронизировать функции асинхронизации

Я пытаюсь получить данные из своего API. Это работает очень хорошо, если я вручную запустил функцию. Мне нужно синхронизировать запрос async.

Мне нужно трижды вызвать свою функцию и дождаться завершения остальных.

makeGetCall(URLstring: "api1") 

ждать, чтобы завершить

makeGetCall(URLstring: "api2") 

ждать, чтобы завершить

makeGetCall(URLstring: "api3") 

Установите это в фоновом режиме и запускать каждые 5 секунд.

func makeGetCall(URLstring: String, update: Bool) { 

    let completeURL = "http://myapi/" + URLstring 


    // Set up the URL request 
    guard let url = URL(string: completeURL) else { 
     print("Error: cannot create URL") 
     return 
    } 
    let urlRequest = URLRequest(url: url) 

    // set up the session 
    let config = URLSessionConfiguration.default 
    let session = URLSession(configuration: config) 

    // make the request 
    let task = session.dataTask(with: urlRequest) { 
     (data, response, error) in 
     // check for any errors 
     guard error == nil else { 
      print("error calling GET on /todos/1") 
      print(error as Any) 
      return 
     } 
     // make sure we got data 
     guard let responseData = data else { 
      print("Error: did not receive data") 
      return 
     } 

      // parse the result as XML 
     if URLstring == "devicelist.cgi" { 
      self.readDevice(XMLData: responseData) 
     } 

     if URLstring == "statelist.cgi" { 
      self.readDeviceData(XMLData: responseData, update: update) 
     } 

     if URLstring == "functionlist.cgi" { 
      self.readGewerke(XMLData: responseData) 
     } 
    } 

    task.resume() 

} 

Может кто-нибудь помочь пожалуйста.

Hagen

Это то, что я пытался с обработчиком завершения:

override func viewDidLoad() { 
    super.viewDidLoad() 

    makeGetCall(input: "statelist.cgi") { 
     (result: Bool) in 
     print("finished statelist") 

    } 
    makeGetCall(input: "devicelist.cgi") { 
     (result: Bool) in 
     print("finished devicelist") 
    } 


    makeGetCall(input: "functionlist.cgi") { 
     (result: Bool) in 
     print("finished functionlist") 
    } 

} 

func makeGetCall(input: String, completion: @escaping (_ result: Bool) -> Void) { 



    let completeURL = "http://192.168.0.25/addons/xmlapi/" + input 


    // Set up the URL request 
    guard let url = URL(string: completeURL) else { 
     print("Error: cannot create URL") 
     return 
    } 
    let urlRequest = URLRequest(url: url) 

    // set up the session 
    let config = URLSessionConfiguration.default 
    let session = URLSession(configuration: config) 

    // make the request 
    let task = session.dataTask(with: urlRequest) { 
     (data, response, error) in 
     // check for any errors 
     guard error == nil else { 
      print("error calling GET on /todos/1") 
      print(error as Any) 
      return 
     } 
     // make sure we got data 
     guard data != nil else { 
      print("Error: did not receive data") 
      return 
     } 
     completion(true) 

    } 

    task.resume() 


} 

Если я ставлю 3 вызова вместе это работало как надо. я, что он должен также работать с НОД, но большинство примеров для быстрой 2.

makeGetCall(input: "devicelist.cgi") { 
     (result: Bool) in 
     print("finished devicelist") 
     self.makeGetCall(input: "functionlist.cgi") { 
      (result: Bool) in 
      print("finished functionlist") 
      self.makeGetCall(input: "statelist.cgi") { 
       (result: Bool) in 
       print("finished statelist") 

      } 
     } 
    } 

Может быть, теперь кто-то может помочь.

Благодаря Hagen

+0

Добавить обработчик завершения 'makeGetCall()' и использовать 'DispatchGroup' для ожидания или получения уведомления. – shallowThought

+0

Я пытался решить свою проблему, но не работал. Может кто-нибудь дать мне совет. – Hagen

+0

Покажите, что вы пробовали с обработчиком завершения – shallowThought

ответ

1

Используйте DispatchGroup, чтобы получить уведомление, когда что-то происходит.

override func viewDidLoad() { 
    super.viewDidLoad() 

    let stateListGroup = DispatchGroup() 

    stateListGroup.enter() 
    makeGetCall(input: "statelist.cgi") { 
     (result: Bool) in 
     print("finished statelist") 
     stateListGroup.leave() 
    } 

    let deviceListGroup = DispatchGroup() 
    deviceListGroup.enter() 

    // the notify closure is called when the (stateList-) groups enter and leave counts are balanced. 
    stateListGroup.notify(queue: DispatchQueue.main) { 
     self.makeGetCall(input: "devicelist.cgi") { 
      (result: Bool) in 
      print("finished devicelist") 
      deviceListGroup.leave() 
     } 
    } 

    let functionListGroup = DispatchGroup() 
    functionListGroup.enter() 

    deviceListGroup.notify(queue: DispatchQueue.main) { 
     self.makeGetCall(input: "functionList") { 
      (result: Bool) in 
      print("finished functionlist") 
      functionListGroup.leave() 
     } 
    } 

    functionListGroup.notify(queue: DispatchQueue.main) { 
     print("update ui here") 
    } 
} 

Печать:

statelist.cgi 
finished statelist 
devicelist.cgi 
finished devicelist 
functionList 
finished functionlist 
update ui here 

держать Также в виду, что обработчик завершения session.dataTask() вызывается на фоне очереди, поэтому я рекомендую направить completion(true) на главной очереди, чтобы избежать неожиданного поведения:

DispatchQueue.main.async { 
    completion(true) 
} 
+0

Спасибо большое. Я изменил его на group.notify (queue: DispatchQueue.main), и теперь он работает так, как должен. – Hagen

+0

О, извините. Написано в метро ... Исправлено это в ответном обновлении. Здесь, в SO, мы благодарим путем голосования или принятия ответа кстати. – shallowThought