Swift开发:如何将MapKit获取的用户坐标存入另一视图控制器的数据库?
解决方案:传递MapKit坐标并存储到数据库
刚好做过类似的需求,给你几个实用的方案,根据你的视图控制器跳转逻辑选最合适的就行:
方案1:闭包(Closure)传递(轻量推荐)
这种方式适合两个视图控制器直接交互,耦合度低,代码简洁:
步骤1:修改MapKit所在的ViewController,添加闭包属性
class MapViewController: UIViewController, CLLocationManagerDelegate { let locationManager = CLLocationManager() // 定义闭包,用于传递坐标 var onCoordinateReceived: ((CLLocationCoordinate2D) -> Void)? override func viewDidLoad() { super.viewDidLoad() locationManager.delegate = self locationManager.requestWhenInUseAuthorization() locationManager.startUpdatingLocation() } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { if let location = locations.first { let coordinate = location.coordinate print(coordinate) // 调用闭包把坐标传出去 onCoordinateReceived?(coordinate) // 拿到坐标后建议停止更新,节省电量 locationManager.stopUpdatingLocation() } } }
步骤2:在数据库ViewController中接收坐标并存储
假设你是通过导航控制器跳转到MapVC,那么在跳转时设置闭包:
// 数据库ViewController中的跳转代码 let mapVC = MapViewController() mapVC.onCoordinateReceived = { [weak self] coordinate in // 这里成功拿到坐标,调用存储方法 self?.saveCoordinateToDB(coordinate: coordinate) } navigationController?.pushViewController(mapVC, animated: true)
然后实现存储方法(对应你提供的数据库代码):
func saveCoordinateToDB(coordinate: CLLocationCoordinate2D) { let building = buildingField.text?.trimmingCharacters(in: .whitespacesAndNewlines) guard let building = building, !building.isEmpty else { print("Building is Empty") return } // 将坐标转为字符串(SQLite常用文本存储,也可以用数值类型) let latitudeStr = String(coordinate.latitude) let longitudeStr = String(coordinate.longitude) // 绑定building(你的原代码) if sqlite3_bind_text(stmt, 5, building, -1, nil) != SQLITE_OK { print("Error binding building") } // 绑定纬度和经度(假设你的数据库表中这两个字段是第6、7位索引,根据实际调整) if sqlite3_bind_text(stmt, 6, latitudeStr, -1, nil) != SQLITE_OK { print("Error binding latitude") } if sqlite3_bind_text(stmt, 7, longitudeStr, -1, nil) != SQLITE_OK { print("Error binding longitude") } // 执行插入操作并处理结果 if sqlite3_step(stmt) != SQLITE_DONE { print("Error inserting data into database") } sqlite3_reset(stmt) }
方案2:通知中心(NotificationCenter)传递
适合跨多个页面、不想直接耦合的场景:
步骤1:MapVC中发送通知
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { if let location = locations.first { let coordinate = location.coordinate print(coordinate) // 发送通知,携带坐标数据 NotificationCenter.default.post( name: NSNotification.Name(rawValue: "CoordinateReceivedNotification"), object: nil, userInfo: ["coordinate": coordinate] ) locationManager.stopUpdatingLocation() } }
步骤2:数据库VC中接收通知
class DatabaseViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // 注册通知观察者 NotificationCenter.default.addObserver( self, selector: #selector(handleCoordinateReceived(_:)), name: NSNotification.Name(rawValue: "CoordinateReceivedNotification"), object: nil ) } @objc private func handleCoordinateReceived(_ notification: Notification) { // 解析坐标数据 guard let coordinate = notification.userInfo?["coordinate"] as? CLLocationCoordinate2D else { print("Invalid coordinate data received") return } // 存储到数据库 saveCoordinateToDB(coordinate: coordinate) } // 记得在页面销毁时移除观察者,避免内存泄漏 deinit { NotificationCenter.default.removeObserver(self) } // 存储方法和方案1一致 func saveCoordinateToDB(coordinate: CLLocationCoordinate2D) { // ... 同方案1的存储代码 } }
方案3:代理(Delegate)模式传递
适合需要更规范组件交互的场景,代码结构更清晰:
步骤1:定义代理协议
// 建议放在MapVC文件顶部或者单独的协议文件中 protocol CoordinateDelegate: AnyObject { func didReceiveCoordinate(_ coordinate: CLLocationCoordinate2D) }
步骤2:MapVC中添加代理属性
class MapViewController: UIViewController, CLLocationManagerDelegate { let locationManager = CLLocationManager() // 代理属性,用weak避免循环引用 weak var delegate: CoordinateDelegate? override func viewDidLoad() { super.viewDidLoad() locationManager.delegate = self locationManager.requestWhenInUseAuthorization() locationManager.startUpdatingLocation() } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { if let location = locations.first { let coordinate = location.coordinate print(coordinate) // 通知代理拿到坐标 delegate?.didReceiveCoordinate(coordinate) locationManager.stopUpdatingLocation() } } }
步骤3:数据库VC遵守代理协议
class DatabaseViewController: UIViewController, CoordinateDelegate { override func viewDidLoad() { super.viewDidLoad() } // 跳转时设置代理 func goToMapVC() { let mapVC = MapViewController() mapVC.delegate = self navigationController?.pushViewController(mapVC, animated: true) } // 实现代理方法 func didReceiveCoordinate(_ coordinate: CLLocationCoordinate2D) { saveCoordinateToDB(coordinate: coordinate) } // 存储方法和方案1一致 func saveCoordinateToDB(coordinate: CLLocationCoordinate2D) { // ... 同方案1的存储代码 } }
内容的提问来源于stack exchange,提问作者Sash Bhagav
相关产品推荐
相关产品推荐

