在我目前的项目中,我希望能够在地图上显示用户的当前位置。
我已经通过Apple提供的requestLocation
方法实现了此功能,但问题是我的代码仍在继续,而不等待requestLocation
函数完成。
流程如下:首先我调用positionController.setPositionViaLocationData()
函数,该函数处理requestLocation
方法的设置和执行。最后,它接收坐标并将它们存储在userPosition
的{{1}}成员中。
在下一行代码中,我想通过PositionController
访问userPosition
,但问题就出现了:
线......
PositionController
...在 var userPosition = positionController.getPosition()
完成之前执行,因此它采用positionController.setPositionViaLocationData()
中存储的默认值。
如何在执行前让代码等待userPosition
positionController.setPositionViaLocationData()
?
我已经阅读了关于闭包和完成管理员的内容,但我不能让那些东西为我工作。
这两个类的代码,首先是调用函数的ViewController:
var userPosition = positionController.getPosition()
现在我的import UIKit
import GoogleMaps
import CoreLocation
class MapViewController: UIViewController, CLLocationManagerDelegate {
let positionController = PositionController()
override func viewDidLoad() {
super.viewDidLoad()
positionController.setPositionViaLocationData()
var userPosition = positionController.getPosition()
setUserPositionMarkerOnMapAndShowMap(userPositionLatitude: userPosition.userLatitude, userPositionLongitude: userPosition.userLongitude)
}
func setUserPositionMarkerOnMapAndShowMap(userPositionLatitude: Double, userPositionLongitude: Double){
let camera = GMSCameraPosition.camera(withLatitude: userPositionLatitude,
longitude: userPositionLongitude, zoom:3)
let mapView = GMSMapView.map(withFrame: CGRect.zero, camera:camera)
let marker = GMSMarker()
self.view = mapView
marker.snippet = "Munich"
marker.appearAnimation = GMSMarkerAnimation.pop
marker.map = mapView
self.view = mapView
}
}
班级:
PositionController
答案 0 :(得分:1)
您可以使用委托通知MapViewController用户位置已更新。
您可以在PositionController类定义
之上添加下一个协议protocol PositionControllerDelegate: class {
func didUpdatePosition(_ newPosition: Position)
}
然后向PositionController
添加一个新的可选属性 weak var delegate: PositionControllerDelegate?
然后调用委托方法:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let locValue: CLLocationCoordinate2D = manager.location!.coordinate
print("locations = \(locValue.latitude) \(locValue.longitude)")
userPosition.latitude = locValue.latitude
userPosition.longitude = locValue.longitude
delegate?.didUpdatePosition(userPosition)
}
在MapViewController方面,您只需要实现协议并将self分配给PositionController的委托。
override func viewDidLoad() {
super.viewDidLoad()
positionController.setPositionViaLocationData()
positionController.delegate = self
var userPosition = positionController.getPosition()
setUserPositionMarkerOnMapAndShowMap(userPositionLatitude: userPosition.userLatitude, userPositionLongitude: userPosition.userLongitude)
}
extension MapViewController: PositionControllerDelegate {
func didUpdatePosition(_ newPosition: Position) {
//Do whatever you want with the position
}
}
答案 1 :(得分:0)
我知道在CLLocationManager.requestLocation()
有值时访问位置信息的两种方法。
在您的位置管理员的委托方法中调用您的函数。
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//call function when you get user location
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
//handle error
}
使用PromiseKit,它提供只在位置管理器更新后才返回的Promise。您需要CLLocationManager.promise()
才能获得在位置管理员更新其位置时返回的承诺。
如果你计划使用大量的异步调用,我会选择PromiseKit,因为它使顺序处理和运行异步函数变得非常简单。但是,了解PromiseKit的工作原理需要一些时间,所以如果你只将它用于这个单一用例,我宁愿选择方法1。
答案 2 :(得分:0)
正如Rob评论的那样,人们不能等待locationRequest
方法结束。
查看代码时,应MapViewController.setUserPositionMarkerOnMapAndShowMap
方法调用PositionController .locationManager(didUpdateLocations)
方法。
这样做的问题是PositionController
并不了解MapViewController
。
一些选项:
将MapViewController
的实例传递给PositionController
。
完全忽略PositionController
控制器并在MapViewController
中实施功能(' didUpdateLocations')。
PS:直接与您的问题无关,但可能表示存在一些混淆,MapViewController
和PositionController
都声明了CLLocationManagerDelegate
协议,但只有PositionController
正在实施它。< / p>