如何使用静默推送通知按需更新用户位置? iOS版

时间:2015-07-15 13:00:13

标签: swift apple-push-notifications core-location appdelegate ios8.3

我想只按需跟踪用户的当前位置。我只需要初始位置,而不是连续更新。我认为最好的方法是向用户发送静默通知,以便获取用户当前的位置一次。接收静默通知工作正常,但LocationManager没有获得该位置的初始修复。 我的位置管理器委托类正常实例化,但在调用位置管理器方法startUpdatingLocation()之后的任何时候都不会触发didUpdateLocations函数。当App从AppDelegate正常启动时:didFinishLaunchingWithOptions,LocationManager会毫无问题地更新用户位置。

我正在开发Xcode 6.3.2到iOS 8.3

我的AppDelegate:DidReceiveRemoteNotification看起来像这样:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler handler: (UIBackgroundFetchResult) -> Void) {

    var bgTask = bgManager()
    bgTask.registerBackgroundTask()
    LocManager.locationMngr.startUpdatingLocation() // LocManager is global variable

    let delayInSeconds = 8.0
    let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
    dispatch_after(popTime, dispatch_get_main_queue()) {
            println(LocManager.updated)
            bgTask.endBackgroundTask()
            handler(UIBackgroundFetchResult.NewData)
    }
}

我首先尝试使用line:

LocManager.locationMngr.startUpdatingLocation()

但是当它不起作用时我添加了后台任务和dispatch_after,以确保我的位置管理器有足够的时间在终止之前检索第一个位置更新。

这是LocationManager类:

class LocationManager: NSObject, CLLocationManagerDelegate {
let locationMngr:CLLocationManager
var coord:CLLocationCoordinate2D
var updated:Bool
    override init() {
        locationMngr = CLLocationManager()
        coord = CLLocationCoordinate2D()
        updated = false
        super.init()
        locationMngr.delegate = self
        locationMngr.desiredAccuracy = kCLLocationAccuracyHundredMeters

        locationMngr.startUpdatingLocation() //Should call didUpdateLocations after some time
    }

    //Doesn't get called in AppDelegate remoteNotifications method
    func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!)
    {
        var loc:CLLocation = locations.first as! CLLocation
        self.coord = loc.coordinate
        locationMngr.stopUpdatingLocation()
        updated = true
    }

和后台管理器类:

class bgManager:NSObject{
    var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
    override init(){
        super.init()
    }
    func registerBackgroundTask() {
        backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {
        [unowned self] in
        self.endBackgroundTask()
        }
    }

    func endBackgroundTask() {
        UIApplication.sharedApplication().endBackgroundTask(backgroundTask)
        backgroundTask = UIBackgroundTaskInvalid
    }
}

收到远程推送的JSON:

"aps" : {
        "sound" : "",
        "content-available" : 1,
        "priority" : 5
    }

我已经在项目功能:背景模式中启用了获取,通知和位置的plist.info密钥和后台模式。 plist.info摘录:

<dict>
    <key>UIRequiredDeviceCapabilities</key>
    <array>
        <string>location-services</string>
        <string></string>
        <string></string>
    </array>
    <key>UIBackgroundModes</key>
    <array>
        <string>remote-notification</string>
        <string>fetch</string>
        <string>location</string>
    </array>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>Your location is needed for this app.</string>
    ...

我为类似的问题疯狂地浏览了SO,并且找不到任何帮助解决方案,包括这个问题:

IOS - Running background task for update user location using swift

Periodic iOS background location updates

Core Location delegate methods not getting called in iOS 8.3 Xcode 6.3.1

Swift: location not being updated when returned from background

2 个答案:

答案 0 :(得分:1)

我遇到了同样的问题并且通过OP的确切步骤无济于事。最后我发现我只是请求了CLLocationManager.requestWhenInUseAuthorization(),它只在应用程序处于前台时提供位置。我必须请求CLLocationManager.requestAlwaysAuthorization()才能让应用在后台请求位置。另外,请确保NSLocationAlwaysUsageDescription文件中包含Info.plist条目。通过这些更改,我可以直接使用CLLocationManager.startUpdatingLocation(),并且能够在后台接收位置更新。

答案 1 :(得分:0)

当应用在后台启动时,在startMonitoringSignificantLocationChanges()为我工作之前致电startUpdatingLocation()

完成后,请务必致电stopMonitoringSignificantLocationChanges()stopUpdatingLocation()