【问题标题】:iOS - How do I wait for the code to finish before going to the next view controller?iOS - 如何在进入下一个视图控制器之前等待代码完成?
【发布时间】:2020-08-16 07:57:24
【问题描述】:

我对编码很陌生,但我一直不知道该怎么做。我试图从一个地址获取用户的地理坐标,使用坐标来计算一些值,然后转到另一个视图控制器,在该控制器中运行一些代码来显示我计算出的值。问题是它找到用户坐标,然后转到下一个视图控制器,它没有显示它所需的计算数据,然后尝试从第一个控制器计算所需的值。如何让这段代码按顺序运行?

我的代码

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

获取数据函数

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


    【解决方案1】:

    将其写入闭包内,因为您的 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
                  }
              }
    }
    

    【讨论】:

    • 我刚刚尝试过,但不幸的是,它仍然决定在 .getData 函数之前进入 segue。 getData 函数包含一个 URLSession,如果这有什么不同的话
    • 我已经发布了方法。对不起,我对这一切都很陌生
    【解决方案2】:

    您在 getCordinate 函数范围之外调用您的 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) 
                   }
    
                  }
        }
    }
    

    【讨论】:

    • 它会给出错误......因为在关闭时你不能在不使用 self 的情况下访问 performSegue :)
    猜你喜欢
    • 1970-01-01
    • 2020-09-28
    • 1970-01-01
    • 2021-07-30
    • 2018-05-20
    • 2011-11-01
    • 1970-01-01
    • 2020-04-29
    • 2022-12-10
    相关资源
    最近更新 更多