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

Swift实现iOS应用被终止/杀死时获取用户位置的方法

iOS应用被终止后追踪位置的解决方案

你的当前代码仅能处理前台/后台的位置更新,应用被完全终止后,常规的startUpdatingLocation无法触发系统唤醒应用。要实现类似Apple Maps、Google Maps的终止后追踪,必须利用iOS提供的重大位置变化服务或地理围栏监测,同时满足权限和配置要求。

核心要求

  1. 权限必须为Always Allow:用户必须授予"始终允许"位置权限,否则应用被终止后系统不会唤醒它。
  2. 配置Info.plist权限描述:添加以下两个键,描述要明确告知用户需求:
    • NSLocationAlwaysAndWhenInUseUsageDescription
    • NSLocationWhenInUseUsageDescription
  3. 开启后台位置更新模式:在Xcode项目的"Signing & Capabilities"中,添加"Background Modes",勾选"Location updates"。

具体实现方案

方案一:重大位置变化服务(推荐,低功耗)

该服务由系统管理,当用户位置发生显著变化(通常几百米,由系统根据移动速度等判断)时,即使应用被终止,系统也会唤醒应用并传递位置更新。

代码修改步骤

  1. 修改位置启动逻辑:
    将原有的startMonitoring()方法替换为同时支持常规更新和重大变化监测:

    func startMonitoring() {
        locManager.allowsBackgroundLocationUpdates = true
        locManager.pausesLocationUpdatesAutomatically = false
        
        // 前台用高精度更新,后台/终止用重大变化服务
        if UIApplication.shared.applicationState == .active {
            locManager.startUpdatingLocation()
        } else {
            locManager.startMonitoringSignificantLocationChanges()
        }
    }
    
  2. 处理应用被唤醒的情况:
    在AppDelegate中添加启动时的位置唤醒处理:

    import UIKit
    import CoreLocation
    
    @main
    class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
        
        var locManager: CLLocationManager!
    
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
            // 检查是否因位置变化被唤醒
            if launchOptions?[.location] != nil {
                locManager = CLLocationManager()
                locManager.delegate = self
                locManager.allowsBackgroundLocationUpdates = true
                // 重新启动重大位置变化监测
                locManager.startMonitoringSignificantLocationChanges()
            }
            return true
        }
        
        // 接收位置更新(应用被终止后唤醒时会调用)
        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            guard let location = locations.last else { return }
            // 处理位置上传逻辑,复用原有postLocation方法
            let viewController = UIApplication.shared.keyWindow?.rootViewController as? ViewController
            viewController?.postLocation(location: location)
            
            // 启动后台任务,确保有足够时间完成上传
            var backgroundTask = UIBackgroundTaskIdentifier.invalid
            backgroundTask = UIApplication.shared.beginBackgroundTask(withName: "LocationUploadTask") {
                UIApplication.shared.endBackgroundTask(backgroundTask)
                backgroundTask = .invalid
            }
            
            DispatchQueue.global().async {
                viewController?.callApi()
                UIApplication.shared.endBackgroundTask(backgroundTask)
                backgroundTask = .invalid
            }
        }
    }
    
  3. 适配应用状态切换:
    在ViewController中监听应用状态切换,动态调整位置更新模式:

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        NotificationCenter.default.addObserver(self, selector: #selector(handleAppActive), name: UIApplication.didBecomeActiveNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(handleAppBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
    }
    
    @objc func handleAppActive() {
        // 回到前台,切换到高精度位置更新
        locManager.stopMonitoringSignificantLocationChanges()
        locManager.startUpdatingLocation()
    }
    
    @objc func handleAppBackground() {
        // 进入后台,切换到重大位置变化服务
        locManager.stopUpdatingLocation()
        locManager.startMonitoringSignificantLocationChanges()
    }
    

方案二:地理围栏监测(适合特定区域追踪)

如果需要在用户进入/离开特定地理区域时唤醒应用,可以使用地理围栏:

// 添加地理围栏
func addGeofence(latitude: CLLocationDegrees, longitude: CLLocationDegrees, radius: CLLocationDistance) {
    let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
    let region = CLCircularRegion(center: coordinate, radius: radius, identifier: "MyGeofence")
    region.notifyOnEntry = true
    region.notifyOnExit = true
    locManager.startMonitoring(for: region)
}

// 监听区域事件(应用被终止后唤醒时会调用)
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
    guard let location = manager.location else { return }
    postLocation(location: location)
}

func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
    guard let location = manager.location else { return }
    postLocation(location: location)
}

关键注意事项

  • 禁止使用Timer后台定时:应用被终止后Timer会完全失效,且Apple不允许此类后台定时任务,仅能通过系统提供的位置服务唤醒应用。
  • 后台任务时长限制:应用被唤醒后,后台任务最多有30秒左右的处理时间,需尽快完成位置上传等操作。
  • 测试注意事项:必须用真机测试,且不能通过Xcode直接终止应用(Xcode终止的应用不会被系统唤醒),需手动从多任务界面划掉应用后测试。

内容的提问来源于stack exchange,提问作者Pankaj Dhameliya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 05:07:33