iOS - 在转到下一个视图控制器之前如何等待代码完成?
iOS - How do I wait for the code to finish before going to the next view 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
}
函数
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()
}
将它写在闭包内,因为你的 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
}
}
}
您在 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)
}
}
}
}
我对编码还很陌生,不知道该怎么做。我试图从一个地址获取用户的地理坐标,使用坐标计算出一些值,然后转到另一个视图控制器,其中一些代码将 运行 显示我计算出的值。问题是它找到用户坐标,然后转到下一个视图控制器,它没有显示它所需的计算数据,然后尝试计算第一个控制器所需的值。如何按顺序将此代码获取到 运行?
我的代码
@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()
}
将它写在闭包内,因为你的 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
}
}
}
您在 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)
}
}
}
}