簡體   English   中英

iOS - 在轉到下一個視圖 controller 之前,如何等待代碼完成?

[英]iOS - How do I wait for the code to finish before going to the next view controller?

我對編碼很陌生,我一直在做什么。 我試圖從一個地址獲取用戶的地理坐標,使用坐標來計算一些值,然后 go 到不同的視圖 controller 將運行一些代碼來顯示我計算出的值。 問題是它找到了用戶坐標,然后轉到下一個視圖 controller,它沒有顯示它所需的計算數據,然后嘗試從第一個 controller 計算所需的值。 如何讓此代碼按順序運行?

我的代碼

@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
}

Function

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?)
    }
}

獲取數據 Function

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()
}

將其寫在閉包內,因為您的 performSegue 在閉包結果之前執行...所以將其寫在閉包內但在主線程上

更新你getData function

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
              }
          }
}

您在 getCordinate function 的 scope 之外調用您的performSegue ,這就是為什么它在單擊按鈕時被調用而不等待完成處理程序完成的原因。

只需將其移入內部即可正常工作。

@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) 
               }

              }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM