首页 > 解决方案 > 在后台特定时间启动位置更新 - Swift (watchOS)

问题描述

我正在开发一个独立的 WatchOS 应用程序,其目的是识别用户何时离开特定区域,从而发送通知。为了做到这一点,该应用程序严重依赖后台位置更新。

到目前为止,应用程序运行良好。它根据 的distanceFilter属性获取位置CLLocationManager。问题是电池。我遵循的方法在执行中保持后台位置更新,即使它们仅在“覆盖”特定距离时才被获取。

我的想法是在用户离开该区域时禁用位置更新,并在夜间禁用此服务。但是,我面临着这种方法的严重问题。

我的主要问题是在后台禁用位置更新不允许我恢复它。我尝试这样做:

似乎没有任何效果。我的问题是:

如果以前被禁用,有办法恢复后台位置更新吗? 先感谢您。

更新n.2:我尝试执行位置更新,WKApplicationRefreshBackgroundTask但它只是忽略requestLocation()功能(@RomuloBM 建议)

//In extension delegate handle() function
case let backgroundTask as WKApplicationRefreshBackgroundTask:
                // Be sure to complete the background ta
                LocMng = LocationManager() // I even tried to create a new element!
                LocMng.LocMng.requestLocation()// it is just ignored
                backgroundTask.setTaskCompletedWithSnapshot(false)

我在 LocationManager 中使用此功能调用后台任务:

//In didUpdateLocation
if background {
            WKExtension.shared().scheduleBackgroundRefresh(withPreferredDate: Date(timeIntervalSinceNow: 30), userInfo: nil){ _ in
                print("Done")
                self.background = false
                self.LocMng.stopUpdatingLocation()
            }
        }

作为参考,这是我的 LocationManager 类:

enum ScanningMode {
    case Precise
    case Normal
}

class LocationManager : NSObject, CLLocationManagerDelegate, UNUserNotificationCenterDelegate, ObservableObject {

    let LocMng = CLLocationManager()
    let NotMng = UNUserNotificationCenter.current()
    var modeOfScanning: ScanningMode!
    var region: CLCircularRegion!
    var previousLocation: CLLocation!
    // variables for position...

    override init() {
        super.init()
        // stuff for my app...

        modeOfScanning = .Precise
        setupManager()
        setupNotification()
        startLocalization()


    }

    private func startLocalization(){
        switch modeOfScanning!{
        case ScanningMode.Precise:
            LocMng.desiredAccuracy = kCLLocationAccuracyBest
            LocMng.distanceFilter = 15
        case ScanningMode.Normal:
            LocMng.desiredAccuracy = kCLLocationAccuracyHundredMeters
            LocMng.distanceFilter = 80
        }
        LocMng.startUpdatingLocation()
    }

    private func setupManager(){
        LocMng.requestAlwaysAuthorization()
        LocMng.delegate = self
        LocMng.desiredAccuracy = kCLLocationAccuracyBest
    }

    private func setupNotification(){
        NotMng.delegate = self
        NotMng.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
                   if granted {
                       print("NotificationCenter Authorization Granted!")
                   }
        }
    }

    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if status == CLAuthorizationStatus.authorizedAlways{
        }
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        LocMng.allowsBackgroundLocationUpdates = true

        // For the sake of clarity, I will cut out this chunk of code and 
        // just showing how I execute my action based on the result of location
        // This is just an example
        actualLocation = locations[length-1]
        //find if in a forget
        if previousLocation != nil{
            if !region.contains(actualLocation!.coordinate) &&     region.contains(previousLocation!.coordinate){
                  //Schedule notification
                  LocMng.stopUpdatingLocation() // <- this does not allow me to resume
            }
        }
        previousLocation = actualLocation
    }

}

标签: swiftcore-locationbatterywatchosbackground-task

解决方案


推荐阅读