我想只根据需要跟踪用户的当前位置。我只需要初始位置,不需要持续更新。我认为最好的方法是向用户发送静音通知,以便获得用户的当前位置。接收静默通知工作得很好,但是LocationManager没有获得位置的初始修复。我的位置管理器委托类正常实例化,但在位置管理器方法startUpdatingLocation()被调用后的任何时候都不会触发didupdatlocations函数。当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>
...
我已经疯狂地浏览了类似的问题,找不到任何有帮助的解决方案,包括这个问题:
IOS -运行后台任务更新用户位置使用swift
iOS后台位置定时更新
Core Location delegate方法在iOS 8.3中没有被调用Xcode 6.3.1
Swift: location从后台返回时未更新
我遇到了同样的问题,并经历了与OP相同的步骤,但无济于事。最终我发现我只请求了CLLocationManager.requestWhenInUseAuthorization()
,它只在应用程序处于前台时提供位置。我必须请求CLLocationManager.requestAlwaysAuthorization()
以便应用程序在后台请求位置。还要确保在Info.plist
文件中有NSLocationAlwaysUsageDescription
条目。有了这些变化,我能够直接使用CLLocationManager.startUpdatingLocation()
,并能够在后台接收位置更新。
当应用程序在后台启动时,在startUpdatingLocation()
工作之前调用startMonitoringSignificantLocationChanges()
。
stopMonitoringSignificantLocationChanges()
和stopUpdatingLocation()