如何使iOS后台应用程序根据位置信息发出通知

如何使iOS后台应用程序根据位置信息发出通知,ios,swift,Ios,Swift,我正在尝试在iOS上实现一个位置导航应用程序。我将有一个设备在我的口袋里,并希望它通知时,标准是基于位置信息的,如谷歌地图导航通知,当你在街上转弯 我想我可以通过CoreLocation和本地通知来实现 以下是我所做的、期望的和实际得到的 OS X El Capitan 10.11.1上的XCode 7.1版(7B91b) 在Xcode中,文件->新建->项目->iOS应用程序->单视图应用程序 将CoreLocation框架添加到项目中 启用“位置更新”后台模式 将值为“hello”的NSL

我正在尝试在iOS上实现一个位置导航应用程序。我将有一个设备在我的口袋里,并希望它通知时,标准是基于位置信息的,如谷歌地图导航通知,当你在街上转弯

我想我可以通过CoreLocation和本地通知来实现

以下是我所做的、期望的和实际得到的

  • OS X El Capitan 10.11.1上的XCode 7.1版(7B91b)
  • 在Xcode中,文件->新建->项目->iOS应用程序->单视图应用程序
  • 将CoreLocation框架添加到项目中
  • 启用“位置更新”后台模式
  • 将值为“hello”的NSLocationAlwaysUsageDescription密钥添加到info.plist
  • 保持ViewController.swift不变
  • 编辑AppDelegate.swift,如下所示

    import UIKit
    import CoreLocation
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
        var window: UIWindow?
        lazy var locationManager: CLLocationManager! = {
            let manager = CLLocationManager()
            manager.desiredAccuracy = kCLLocationAccuracyBest
            manager.pausesLocationUpdatesAutomatically = false
            manager.delegate = self
            manager.requestAlwaysAuthorization()
            return manager
        }()
        var lastNotifictionDate = NSDate()
    
        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            let settings = UIUserNotificationSettings(forTypes: [.Alert], categories: nil)
            UIApplication.sharedApplication().registerUserNotificationSettings(settings)
            locationManager.startUpdatingLocation()
            return true
        }
    
        func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            // Do something interesting.
            // I make this function return immediately until 10sec passed after previous notification.
            let now = NSDate()
            if lastNotifictionDate.dateByAddingTimeInterval(10).compare(now) == .OrderedDescending {
                //NSLog("Not yet")
                return
            }
            //NSLog("It's time")
            lastNotifictionDate = now
    
            // Fire local notification, without sound configured for simplicity.
            let notification = UILocalNotification()
            notification.alertBody = "Hello"
            UIApplication.sharedApplication().presentLocalNotificationNow(notification)
        }
    
        // ... other methods are untouched ...
    }
    
该应用程序在模拟器上工作,正如我所期望的,即

  • 在iPhone 5模拟器中运行该应用程序,并允许提供位置和通知服务
  • 按下home按钮(Shift-Command-H)
  • 在模拟器菜单中,调试->位置->自由驱动器
  • 该应用程序每10秒显示一次本地通知警报
该应用程序在我的设备iphone5和ios9.1上的表现有所不同

  • 通过Xcode运行应用程序并允许位置和通知服务
  • 按下主页按钮
  • 设备不会在主屏幕或通知中心上显示通知警报
  • 然后,我轻触设备上的应用图标,打开应用前景,打开通知中心,发现两个通知。如果我等待50秒,我希望新出现5个通知,但没有新出现通知
我知道模拟器的行为与实际设备不同。例如,模拟器在后台显示控制台上的NSLog()和print()输出,而实际设备则不显示


我猜我没有为设备配置某些东西,或者我正试图以不可行的方式进行配置,但我找不到它是什么。您能告诉我出了什么问题以及如何修复它吗?

将CLLocationManager的AllowsBackgroundLocationUpdate设置为true解决了我的问题

manager.allowBackgroundLocationupdates = true

如果为false(默认),则更新在挂起时停止。更新发生在前台或后台。

那么你确定你确实在设备上收到了后台更新吗?@MitchellCurrie是的,我通过添加
日期来验证我在后台收到了位置更新。追加(NSDate())
在locationManager函数中。那么问题是尝试安排本地通知?@MitchellCurrie Yes。我应该澄清一下。你能从主线程成功地在前台安排吗?还要检查设备上的权限,以确保它是允许的