You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
  }

问题原因

  1. locationManager是局部变量,getLocation方法执行完毕后会被销毁,无法持续监听位置更新
  2. 未设置CLLocationManager的代理,导致didUpdateLocations回调永远不会触发
  3. 提前调用result("updating location"),直接结束Flutter端的异步调用,后续无法接收位置数据
  4. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 12:47:41