更新正如@davidgyoung 在另一个问题上向我指出的那样,这种使用UNLocationNotificationTrigger 的方法不会向您报告主要和次要标识符,因为它使用了监控API 和不是范围,这是您获取主要和次要数字所需要的。这限制了您可以使用此包装 API 执行的所有操作。这确实很方便,但没有人们希望的那么有用。
据我所知,新的(iOS 10、Swift 3)方法是使用UserNotifications 库并使用UNNotificationRequest 实现它。您可以通过UNLocationNotificationTrigger 将信标区域传递给它。现在我知道您想要的东西似乎与直觉相反(应用程序关闭时的通知),但是,您想将NSLocationWhenInUseUsageDescription 键添加到您的Info.plist 而不是NSLocationAlwaysUsageDescription。我不确定为什么会这样,但这是必要的步骤。这是我用于创建(iBeacon)基于位置的通知的代码:
// Ensure you use a class variable in order to ensure the location
// manager is retained, otherwise the alert message asking you to
// authorize it will disappear before you can tap "allow" which
// will keep it from working
let locationManager = CLLocationManager()
// ...
// Somewhere in your class (e.g. AppDelegate or a ViewController)
self.locationManager.requestWhenInUseAuthorization()
let region = CLBeaconRegion(proximityUUID: UUID(uuidString: "YOUR-UNIQUE-UUID-STRING")!, identifier: "com.yourcompany.youridentifier")
region.notifyOnEntry = true
region.notifyOnExit = false
let content = UNMutableNotificationContent()
content.title = "Notification Title"
content.body = "Body text goes here"
// Not sure if repeats needs to be set to true here, but that's
// how I've implemented it
let trigger = UNLocationNotificationTrigger(region: region, repeats: true)
// Use the same identifier each time to ensure it gets overwritten
// in the notification system
let identifier = "BeaconLocationIdentifier"
let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)
// This is probably unnecessary since we're using the same identifier
// each time this code is called
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
// Make sure you set the notification center's delegate. My
// containing class is the AppDelegate. I implement the delegate
// methods there.
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in
})
// Not sure if this is required either, but after I added this, everything
// started working
self.locationManager.startRangingBeacons(in: region)
确保实现通知中心委托方法:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
// Called when the notification has been swiped or tapped by the user
// Do something with the response here
// Make sure you call the completion handler
completionHandler()
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// Called when the app is in the foreground
// Do something with the notification here
// Make sure you call the completion handler
completionHandler([.alert, .sound])
}
最后,您需要先授权通知才能让这一切正常工作。您可以使用此代码来执行此操作:
let options: UNAuthorizationOptions = [.alert,.sound]
UNUserNotificationCenter.current().requestAuthorization(options: options) {
(granted, error) in
if !granted {
debugPrint("Something went wrong")
} else {
debugPrint("Notifications granted")
}
}
最后一个提示:我有一个旧金属罐,它(有点)用作我正在使用的信标的法拉第笼。我只是在那里关闭我的信标一分钟左右,然后应用程序检测到我已经超出范围。这比试图从信标走得足够远或卸下电池(这对我来说似乎根本不起作用)更方便。有些信标的信号比其他信标强,并且可能仍然可以通过锡,所以 YMMV。