Swift与Flutter自定义平台代码传递iOS位置问题求助
iOS原生Swift获取位置并传递给Flutter的问题解决
我需要获取iOS设备的位置,但不使用Flutter插件,需通过Swift代码获取并传递至Flutter。我没有Swift开发经验,已编写如下代码,但运行后仅返回Swift代码getLocation函数中的字符串“updating location”,无法获取实际位置坐标。
iOS端(Swift)原代码
import UIKit import Flutter import CoreLocation @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let testChannel = FlutterMethodChannel(name: "com.example.testFlutter/test", binaryMessenger: controller.binaryMessenger) testChannel.setMethodCallHandler({ [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in // This method is invoked on the UI thread. if call.method == "getLocation"{ self?.getLocation(result: result) } else{ result(FlutterMethodNotImplemented) return } }) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } private func getLocation(result: FlutterResult){ var locationManager: CLLocationManager? locationManager?.requestAlwaysAuthorization() if CLLocationManager.locationServicesEnabled() { locationManager?.startUpdatingLocation() result("updating location") } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation], result: FlutterResult) { result("testing") guard let locValue: CLLocationCoordinate2D = manager.location?.coordinate else { return } result("location = \(locValue.latitude) \(locValue.longitude)") } }
Flutter端原代码
static const platform = MethodChannel('com.example.testFlutter/test'); printMsgFromiOS() async { try { final String result = await platform.invokeMethod('getLocation'); print(result); } on PlatformException catch (e) { print(e.message); } } @override void initState() { super.initState(); printMsgFromiOS(); }
问题原因
locationManager是局部变量,getLocation方法执行完毕后会被销毁,无法持续监听位置更新- 未设置
CLLocationManager的代理,导致didUpdateLocations回调永远不会触发 - 提前调用
result("updating location"),直接结束Flutter端的异步调用,后续无法接收位置数据 didUpdateLocations方法的签名不符合CLLocationManagerDelegate规范,额外添加的result参数导致系统无法回调该方法
修正后的代码
iOS端(Swift)代码
import UIKit import Flutter import CoreLocation @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate, CLLocationManagerDelegate { // 全局变量保存位置管理器,避免被销毁 private var locationManager: CLLocationManager? // 保存Flutter回调,用于获取到位置后返回结果 private var locationResult: FlutterResult? override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let testChannel = FlutterMethodChannel(name: "com.example.testFlutter/test", binaryMessenger: controller.binaryMessenger) testChannel.setMethodCallHandler({ [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in if call.method == "getLocation"{ self?.getLocation(result: result) } else{ result(FlutterMethodNotImplemented) return } }) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } private func getLocation(result: FlutterResult){ locationResult = result locationManager = CLLocationManager() locationManager?.delegate = self // 根据需求选择权限类型,这里使用前台权限 locationManager?.requestWhenInUseAuthorization() if CLLocationManager.locationServicesEnabled() { locationManager?.desiredAccuracy = kCLLocationAccuracyBest locationManager?.startUpdatingLocation() } else { result(FlutterError(code: "LOCATION_DISABLED", message: "位置服务未开启", details: nil)) } } // 符合Delegate规范的位置更新回调 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let location = locations.last, let result = locationResult else { return } // 获取到位置后停止更新 manager.stopUpdatingLocation() // 用字典传递坐标,方便Flutter解析 let locationData = [ "latitude": location.coordinate.latitude, "longitude": location.coordinate.longitude ] result(locationData) locationResult = nil } // 处理权限状态变化 func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { guard let result = locationResult else { return } switch status { case .denied, .restricted: result(FlutterError(code: "PERMISSION_DENIED", message: "位置权限被拒绝", details: nil)) locationResult = nil default: break } } // 处理位置获取失败 func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { guard let result = locationResult else { return } result(FlutterError(code: "LOCATION_ERROR", message: error.localizedDescription, details: nil)) locationResult = nil } }
Flutter端代码
static const platform = MethodChannel('com.example.testFlutter/test'); Future<void> printMsgFromiOS() async { try { // 接收字典类型的位置数据 final Map<dynamic, dynamic> result = await platform.invokeMethod('getLocation'); double latitude = result['latitude']; double longitude = result['longitude']; print("获取到位置:纬度=$latitude,经度=$longitude"); } on PlatformException catch (e) { print("获取位置失败:${e.message}"); } } @override void initState() { super.initState(); printMsgFromiOS(); }
额外配置
需要在iOS项目的Info.plist中添加位置权限描述:
<!-- 前台使用位置权限 --> <key>NSLocationWhenInUseUsageDescription</key> <string>需要获取您的位置信息以提供服务</string> <!-- 如果需要后台位置权限,添加以下内容 --> <key>NSLocationAlwaysAndWhenInUseUsageDescription</key> <string>需要在后台获取您的位置信息</string>
内容的提问来源于stack exchange,提问作者Muhammad Zeeshan
相关产品推荐
相关产品推荐

