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

Flutter iOS调用location包获取位置时应用立即崩溃

Flutter location包调用时崩溃的解决方案

问题描述

在Flutter v3.0.5中使用location ^4.4.0包获取设备位置时,调用该包的任意方法都会导致应用崩溃。已在Info.plist中添加相关权限配置:

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>...</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>...</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>...</string>
<key>UIBackgroundModes</key>
<string>location</string>

实现代码直接取自包示例,但在location.serviceEnabled()处崩溃:

user_location.dart代码

import 'package:location/location.dart';

class UserLocation {
  Location location = Location();

  late bool _serviceIsEnabled;
  late PermissionStatus _permissionGranted;
  late LocationData _locationData;

  Future<LocationData?> getLocation() async {
    print("Getting location");
   
    _serviceIsEnabled = await location.serviceEnabled(); // 在此处崩溃 <-

    if (!_serviceIsEnabled) {
      _serviceIsEnabled = await location.requestService();
      if (!_serviceIsEnabled) return null;
    }

    _permissionGranted = await location.hasPermission();

    if (_permissionGranted == PermissionStatus.denied) {
      _permissionGranted = await location.requestPermission();
      if (_permissionGranted != PermissionStatus.granted) {
        return null;
      }
    }

    _locationData = await location.getLocation();
    return _locationData;
  }
}

main.dart相关代码

Future main() async {
  await dotenv.load();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  LocationData? _userLocation;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      setState(() async {
        final location = await UserLocation().getLocation();
        _userLocation = location;
      });
    });
  }
}

解决方案

  • 配置iOS端初始化代码
    location包在iOS上需要额外的初始化配置,否则会因插件注册问题崩溃。修改ios/Runner/AppDelegate.swift(Swift项目):

    import UIKit
    import Flutter
    import location
    
    @UIApplicationMain
    @objc class AppDelegate: FlutterAppDelegate {
      override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)
        // 添加location插件注册回调
        LocationPlugin.setPluginRegistrantCallback { registry in
          GeneratedPluginRegistrant.register(with: registry)
        }
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
      }
    }
    

    若为Objective-C项目,修改ios/Runner/AppDelegate.m:

    #import "AppDelegate.h"
    #import "GeneratedPluginRegistrant.h"
    #import <location/LocationPlugin.h>
    
    @implementation AppDelegate
    
    - (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      [GeneratedPluginRegistrant registerWithRegistry:self];
      // 添加location插件注册回调
      [LocationPlugin setPluginRegistrantCallback:^(NSObject<FlutterPluginRegistry>* registry) {
        [GeneratedPluginRegistrant registerWithRegistry:registry];
      }];
      return [super application:application didFinishLaunchingWithOptions:launchOptions];
    }
    
    @end
    
  • 修复异步调用的错误写法
    setState的回调不能是异步函数,这会导致状态更新逻辑异常。修改_MyHomePageState的initState方法:

    @override
    void initState() {
      super.initState();
      WidgetsBinding.instance.addPostFrameCallback((_) async {
        final location = await UserLocation().getLocation();
        setState(() {
          _userLocation = location;
        });
      });
    }
    

    将async移至addPostFrameCallback的回调函数上,确保异步操作完成后再调用setState更新状态。

  • 清理项目缓存并重新构建
    执行以下命令清理旧的构建缓存,避免残留文件导致的问题:

    flutter clean
    flutter pub get
    cd ios && pod install && cd ..
    flutter run
    
  • 确保权限描述不为空
    Info.plist中的权限说明字符串不能是占位符...,需要替换为实际的用途说明,比如:

    <key>NSLocationWhenInUseUsageDescription</key>
    <string>需要获取您的位置信息以提供定位服务</string>
    

内容的提问来源于stack exchange,提问作者Ryan Roberts

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 15:27:49