2017-01-20 2 views
0

У меня есть эта длинная функция здесь, которая создает кучу вызовов API, анализирует данные и возвращает два массива, представляющие кучу визитных мест (один массив содержит широты, один удерживает широты). Проблема, с которой я сталкиваюсь, определяет, когда будут заполнены два массива. В идеале я хотел бы иметь возможность разместитьSwift - Проблемы с вызовами API/CompletionHandler/URLSessions

print("ArrayCount = \(self.latArray.count)") 

где-то в моем коде и получить один оператор печати в консоли для чтения ArrayCount = 123. Однако везде я помещаю заявление для печати, я получаю либо счетчик массива из 0 или цикл значений, которые печатаются по мере их добавления (1..2..3 .. ... ..123). Заранее спасибо!

func someFunction() 
{ 
    let url:URL = URL(string: "...") 

    let task = URLSession.shared.dataTask(with: URLRequest(url: url)) 
    { 
     data, response, error in 

     if error != nil 
     { 
      print("ERROR IN API REQUEST: \(error!.localizedDescription)") 
     } 

     else 
     { 
      do 
      { 
       if let parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] 
       { 
        if let layerOne = parsedData["one"] as? [String: Any] 
        { 
         if let layerTwo = layerOne["two"] as? [[String: Any]] 
         { 
          for layerThree in layerTwo 
          { 
           if let variableName = layerThree["value"] as? String 
           { 
            let innerUrl:URL = URL(string: "...")! 

            let innerTask = URLSession.shared.dataTask(with: URLRequest(url: innerUrl)) 
            { 
             data, response, error in 

             if error != nil 
             { 
              print("ERROR IN API REQUEST: \(error!.localizedDescription)") 
             } 

             else 
             { 
              do 
              { 
               if let parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] 
               { 
                if let layerA = parsedData["A"] as? [String: Any] 
                { 
                 if let lat = layerA["Latitude"] as? String, let long = layerA["Longitude"] as? String 
                 { 
                  self.latArray.append(lat) 
                  self.longArray.append(lon) 
                 } 
                } 
               } 
              } 

              catch 
              { 
               print("ERROR IN JSON SERIALIZATION") 
              } 
             } 
            } 
            innerTask.resume() 
           } 
          } 
         } 
        } 
       } 
      } 

      catch 
      { 
       print("ERROR IN JSON SERIALIZATION") 
      } 
     } 
    } 

    task.resume() 
} 
+0

Можете ли вы дать образец JSON, который вы получаете? То, как вы разбираете этот JSON, выглядит странно. – AdamPro13

+0

Прошли ли вы и заменили все ваши переменные и индексы, чтобы использовать произвольные произвольные имена? Это довольно похоже на то, что вы пытаетесь проанализировать ответ API из API Google Адресов. Почему бы просто не опубликовать исходный код? Таким образом, другим людям легче помочь с вашей проблемой. –

+0

Вы можете сделать несколько условных привязок для оператора 'if'. Вам не нужно все это сумасшедшее гнездование. – Alexander

ответ

0

Я не знаю точно, что вы пытаетесь сделать, но как только я разбавлять свой невероятно подробный код и попытался понять это, я думаю, что вывод о том, что вы только хотите, чтобы записать подсчет массива после последней итерации вашего внутреннего цикла. Например:

Вместо того, чтобы сделать это: for layerThree in layerTwo

сделать это: for (index, layerThree) in layerTwo.enumerated()

Затем, после того, как вы добавите широту/долготу значения, добавьте эту проверку:

if index == layerTwo.count - 1 //if this is our last inner loop 
{ 
    //print the array counts 
    print("Lat count: \(latArray.count)") 
    print("Long count: \(longArray.count)") 
} 

Это должно работать в твоем случае. Однако я полностью не согласен с выполнением этого просто из-за отсутствия переносимости и повторного использования вашего кода. Кроме того, существует немало хороших языковых конструкций, которые игнорируются. Неустанные вложенные блоки if let могут быть значительно уменьшены с помощью нескольких хороших операторов guard. Кроме того, учитывая, что вы все равно не обрабатываете свои ошибки в любом блоке catch, можете просто удалить их и вместо этого выбрать try?. Одним из самых быстрых способов обработки вещей было бы просто включить обработчик завершения в самой функции, чтобы логика печати счетчика массива могла обрабатываться в другом месте. Я буду включать некоторые примеры кода, как я хотел бы очистить вещи:

func someFunction(completion: (([String], [String]) -> Void)?) 
{ 
    let url = URL(string: "...")! 
    var latArray: [String] = [] 
    var longArray: [String] = [] 

    let task = URLSession.shared.dataTask(with: URLRequest(url: url), 
     completionHandler: { (data, response, error) -> Void in 
      guard error == nil else 
      { 
       print("ERROR IN API REQUEST: \(error?.localizedDescription)") 
       return 
      } 

      guard let parsedData = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments), 
       let parsedDict = parsedData as? [String: Any], 
       let layerOne = parsedDict["one"] as? [String: Any], 
       let layerTwo = layerOne["two"] as? [[String: Any]] else 
      { 
       print("JSON OBJECT DOES NOT MATCH EXPECTED PATTERN") 
       return 
      } 

      for (index, layerThree) in layerTwo.enumerated() 
      { 
       guard let _ = layerThree["value"] as? String else 
       { 
        print("Skip this iteration (I guess?)") 
        continue 
       } 

       let innerUrl = URL(string: "...")! 
       let innerTask = URLSession.shared.dataTask(with: URLRequest(url: innerUrl), 
        completionHandler: { (data, response, error) -> Void in 
         guard error == nil else 
         { 
          print("ERROR IN API REQUEST: \(error?.localizedDescription)") 
          return 
         } 

         guard let parsedData = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments), 
          let parsedDict = parsedData as? [String: Any], 
          let layerA = parsedDict["A"] as? [String: Any], 
          let lat = layerA["Latitude"] as? String, 
          let long = layerA["Longitude"] as? String else 
         { 
          print("Something went wrong") 
          return 
         } 

         latArray.append(lat) 
         longArray.append(long) 

         if index == layerTwo.count - 1 //if this is our last inner loop 
         { 
          completion?(latArray, longArray) 
         } 
        } 
       ) 
       innerTask.resume() 
      } 
     } 
    ) 

    task.resume() 
} 

someFunction(completion: { (latArray, longArray) -> Void in 
    //print the array counts 
    print("Lat count: \(latArray.count)") 
    print("Long count: \(longArray.count)") 
}) 

Это еще может быть улучшена намного дальше, хотя и основаны на ваш вопрос я не вижу, что я лично должен уделять больше времени на строительство это для тебя. Было бы лучше, если бы вы придумали несколько собственных методов для создания приложения с более читаемым и многоразовым кодом.

Смежные вопросы