iOS - Как мне дождаться завершения кода sh, прежде чем перейти к следующему контроллеру представления? - PullRequest
1 голос
/ 01 мая 2020

Я очень новичок в кодировании, и я застрял на том, что делать. Я пытаюсь получить гео-координаты пользователя по адресу, используйте координаты, чтобы выяснить некоторые значения, затем go для другого контроллера представления, где будет запущен некоторый код для отображения значений, которые я выяснил. Проблема в том, что он находит пользовательские координаты, затем переходит к следующему контроллеру представления, где у него нет рассчитанных данных, необходимых для его отображения, затем пытается вычислить значения, необходимые из первого контроллера. Как заставить этот код работать по порядку?

Мой код

@IBAction func BSearch(_ sender: UIButton) {
    getCoordinate(addressString: AdressInput) { coordinate, error in
        if error != nil {
            // Error
            return
        } else {
            user_lat = String(format: "%f", coordinate.latitude)
            user_long = String(format: "%f", coordinate.longitude) // Program gets this first
            self.getData(savedLat: user_lat, savedLong: user_long) // Lastly goes here
        }
    }
    performSegue(withIdentifier: "TimeNavigation", sender: self) // Goes here second
}

Функция

func getCoordinate(addressString: String, completionHandler: @escaping (CLLocationCoordinate2D, NSError?) -> Void ) {
    let geocoder = CLGeocoder()
    geocoder.geocodeAddressString(addressString) { (placemarks, error) in
        if error == nil {
            if let placemark = placemarks?[0] {
               let location = placemark.location!
               completionHandler(location.coordinate, nil)
               return
            }
        }
        completionHandler(kCLLocationCoordinate2DInvalid, error as NSError?)
    }
}

Функция getData

func getData(savedLat: String, savedLong: String) {
    guard let url = URL(string: "http://127.0.0.1:5000/api/lat/\(savedLat)/long/\(savedLong)") else{return}

    URLSession.shared.dataTask(with: url) { (data, response, err) in
        guard let data = data else { return }

        var dataAsString = String(data: data, encoding: .utf8)

        let splits = dataAsString?.components(separatedBy: "|")

        let Counter:Int = splits?.count ?? 0

        for n in 0...(Counter-1){
            let splits2 = splits?[n].components(separatedBy: ",")
            for x in 0...9 {
                dataArray[n][x] = String(splits2?[x] ?? "nil")
            }
        }
    }.resume()
}

Ответы [ 2 ]

2 голосов
/ 01 мая 2020

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

Обновите функцию getData

typealias CompletionHandler = (_ success:Bool) -> Void
    func getData(savedLat:String,savedLong:String, completionBlock:@escaping CompletionHandler){

    guard let url = URL(string: "http://127.0.0.1:5000/api/lat/\(savedLat)/long/\(savedLong)") else{return}

    URLSession.shared.dataTask(with: url) { (data, response, err) in
        guard let data = data else {
            completionBlock(false)
            return
        }

        var dataAsString = String(data: data, encoding: .utf8)

       let splits = dataAsString?.components(separatedBy: "|")
       let Counter:Int = splits?.count ?? 0

            for n in 0...(Counter-1){
               let splits2 = splits?[n].components(separatedBy: ",")
                    for x in 0...9 {
                       dataArray[n][x] = String(splits2?[x] ?? "nil")

                               }
                            completionBlock(true)
                         }

                  }.resume()
       }

И затем ваш метод BSearch

@IBAction func BSearch(_ sender: UIButton) {
   getCoordinate(addressString: "AdressInput") { coordinate, error in
      if error != nil {
         // Error
         return
      }
      else {

        user_lat = String(format: "%f", coordinate.latitude)
        user_long = String(format: "%f", coordinate.longitude) // Program gets this first
        self.getData(savedLat: "user_lat", savedLong: "user_long", completionBlock: {[weak self] success in

        DispatchQueue.main.async {
          self?.performSegue(withIdentifier: "TimeNavigation", sender: self)
          }
                }) // Lastly goes here
              }
          }
}
0 голосов
/ 01 мая 2020

Вы вызываете ваш performSegue вне области действия функции getCordinate, поэтому она вызывается по нажатию кнопки, а не ожидает завершения обработчика завершения до sh.

Просто переместите его внутрь, и он будет работать нормально.

@IBAction func BSearch(_ sender: UIButton) {
   getCoordinate(addressString: AdressInput) { coordinate, error in
            if error != nil {
              // Error
              return
            }
            else {

               user_lat = String(format: "%f", coordinate.latitude)
               user_long = String(format: "%f", coordinate.longitude) // Program gets this first
               self.getData(savedLat: user_lat, savedLong: user_long) // Lastly goes here
               DispatchQueue.main.async { //when performing UI related task, it should be on main thread
                 self.performSegue(withIdentifier: "TimeNavigation", sender: self) 
               }

              }
    }
}
...