Swift中如何在一个ViewController保存当前位置坐标并传递至另一个?
Swift页面间位置传递问题解决方案
嘿,我来帮你搞定这个位置传递的问题~ 先给你解答最关心的点:用函数返回值保存坐标其实不太合理,因为定位是异步操作——你调用定位方法后,系统需要一点时间才能拿到位置数据,同步的函数返回值大概率会先返回空或者默认值,等真正拿到位置的时候,返回值早就没用了。
下面给你几种适合异步场景的传值方案,都是Swift开发里常用的:
方案一:闭包回调 + 属性赋值(适合直接跳转的场景)
如果是从VC A跳转到VC B,你可以等定位完成后,再把位置传给VC B的属性。比如:
首先在VC B里定义一个接收位置的属性:
import CoreLocation class ViewControllerB: UIViewController { var userLocation: CLLocationCoordinate2D? override func viewDidLoad() { super.viewDidLoad() // 拿到位置后在这里做展示逻辑 if let location = userLocation { print("展示位置:\(location.latitude), \(location.longitude)") } } }
然后在VC A里,等定位回调拿到位置后,再跳转并赋值:
import CoreLocation class ViewControllerA: UIViewController, CLLocationManagerDelegate { let locationManager = CLLocationManager() override func viewDidLoad() { super.viewDidLoad() locationManager.delegate = self locationManager.requestWhenInUseAuthorization() locationManager.startUpdatingLocation() } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let currentLocation = locations.last?.coordinate else { return } locationManager.stopUpdatingLocation() // 拿到位置就停止更新 // 跳转到VC B并传值 let vcB = storyboard?.instantiateViewController(withIdentifier: "ViewControllerB") as! ViewControllerB vcB.userLocation = currentLocation navigationController?.pushViewController(vcB, animated: true) } }
方案二:单例类存储(适合多页面共享位置)
如果你的APP不止VC B需要这个位置,可以创建一个全局的单例类来保存位置,VC A更新它,VC B直接读取:
// 全局单例类 import CoreLocation class LocationStore { static let shared = LocationStore() private init() {} // 禁止外部实例化 var userCurrentLocation: CLLocationCoordinate2D? }
VC A里更新位置:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let currentLocation = locations.last?.coordinate else { return } locationManager.stopUpdatingLocation() LocationStore.shared.userCurrentLocation = currentLocation }
VC B里读取展示:
override func viewDidLoad() { super.viewDidLoad() if let location = LocationStore.shared.userCurrentLocation { print("展示位置:\(location.latitude), \(location.longitude)") } }
方案三:通知中心(适合位置动态更新的场景)
如果VC B已经在后台,或者需要实时接收位置更新,可以用通知中心:
VC B里注册通知:
override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(handleLocationUpdate(_:)), name: NSNotification.Name("UserLocationUpdated"), object: nil) } @objc func handleLocationUpdate(_ notification: Notification) { if let location = notification.userInfo?["location"] as? CLLocationCoordinate2D { print("收到更新后的位置:\(location.latitude), \(location.longitude)") // 这里做展示逻辑 } } // 记得销毁通知 deinit { NotificationCenter.default.removeObserver(self) }
VC A里发送通知:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let currentLocation = locations.last?.coordinate else { return } locationManager.stopUpdatingLocation() NotificationCenter.default.post(name: NSNotification.Name("UserLocationUpdated"), object: nil, userInfo: ["location": currentLocation]) }
小提醒
不管用哪种方案,都要注意定位权限的申请,info.plist里记得加NSLocationWhenInUseUsageDescription或者NSLocationAlwaysAndWhenInUseUsageDescription的描述,不然定位会失败。
另外,如果你的跳转逻辑是用户主动触发(比如点击按钮),那最好在按钮点击前就提前启动定位,确保点击时已经拿到位置,或者在按钮点击后等待定位完成再跳转。
内容的提问来源于stack exchange,提问作者Cheng
相关产品推荐
相关产品推荐

