iOS - 如何等待代码完成后再进入下一个视图控制器?

问题描述 投票:1回答:2

我是一个非常新的编码,我被卡住了,不知道该怎么做。我试图从一个地址中获取用户的地理坐标,使用坐标计算出一些值,然后转到不同的视图控制器,在那里运行一些代码来显示我计算出的值。问题是它找到了用户的坐标,然后转到下一个视图控制器,在那里它没有计算出需要显示的数据,然后试图从第一个控制器计算出需要的值。我怎样才能让这段代码按顺序运行?

我的代码

@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()
}
ios swift xcode uikit interface-builder
2个回答
2
投票

把它写在闭包里面,因为你的 performSegue 会在闭包结果之前执行......所以把它写在闭包里面,但在主线程上。

更新你的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
              }
          }
}

-1
投票

你在叫你的 performSegue 在getCordinate函数的范围之外,这就是为什么它在点击按钮时被调用,而不是等待完成处理程序完成。

只要把它移到里面就可以了。

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

              }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.