在自定义Sirikit、iOS、swift中访问用户当前位置
我创建了一个自定义Sirikit intent,在IntentHandler类中,我找不到默认设置了位置隐私“Always”的用户位置。 请看代码在自定义Sirikit、iOS、swift中访问用户当前位置,ios,swift,ios12,sirikit,Ios,Swift,Ios12,Sirikit,我创建了一个自定义Sirikit intent,在IntentHandler类中,我找不到默认设置了位置隐私“Always”的用户位置。 请看代码 import Foundation import CoreData import CoreLocation class PhotoOfTheDayIntentHandler: NSObject, PhotoOfTheDayIntentHandling { let context = CoreDataStorage.mainQueueConte
import Foundation
import CoreData
import CoreLocation
class PhotoOfTheDayIntentHandler: NSObject, PhotoOfTheDayIntentHandling {
let context = CoreDataStorage.mainQueueContext()
var counter : DistanceEntity?
var locationManger = CLLocationManager()
func confirm(intent: PhotoOfTheDayIntent, completion: @escaping (PhotoOfTheDayIntentResponse) -> Void) {
completion(PhotoOfTheDayIntentResponse(code: .ready, userActivity: nil))
}
func handle(intent: PhotoOfTheDayIntent, completion: @escaping (PhotoOfTheDayIntentResponse) -> Void) {
self.context.performAndWait{ () -> Void in
let counter = NSManagedObject.findAllForEntity("DistanceEntity", context: self.context)
if (counter?.last != nil) {
self.counter = (counter!.last as! DistanceEntity)
let currentLocation: CLLocation = locationManger.location!
let greenLocation = CLLocation(latitude:self.counter!.latitude, longitude: self.counter!.longitude)
let distanceInMeters = currentLocation.distance(from: greenLocation) // result is in meters
debugPrint("distanceInMeters",distanceInMeters)
completion(PhotoOfTheDayIntentResponse.success(photoTitle: "\(distanceInMeters) Meter"))
completion(PhotoOfTheDayIntentResponse.success(photoTitle: "\(self.counter!.distance) Meter"))
}
}
}
}
如果我对位置管理器进行注释,它会崩溃。TLDR:在主线程中创建
CLLocationManager
,它应该可以工作
import CoreLocation
class WhateverYouWant: NSObject{
let userLocation = UserLocationManager()
func handle(intent: DistanceOfGreenIntent, completion: @escaping (DistanceOfGreenIntentResponse) -> Void) {
if(userLocation.locationManager.location == nil){
userLocation.locationManager.requestAlwaysAuthorization()
userLocation.locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
if let currentLocation: CLLocation = userLocation.locationManager.location{
self.context.performAndWait{ () -> Void in
completion(DistanceOfGreenIntentResponse.success(distanceString:"Please Start a game on course to get distances"))
}else{
debugPrint("Please enable your location")
completion(DistanceOfGreenIntentResponse.success(distanceString: "Please enable your location to get distances"))
}}
}
如果您在mac上打开Console.app并监视正在运行Siri Intent的设备,您可能会收到类似以下消息: 在主线程以外的线程上执行的调度队列上创建了位置管理器(0xe86bdf0) (就像这个问题:) 问题是核心位置必须在连接到主循环的运行循环中创建。最简单的解决方案是在主循环中创建
CLLocationManager
下面是一个使用位置的示例意图处理程序
import Foundation
import CoreLocation
class ExampleIntentHandler: NSObject, ExampleIntentIntentHandling, CLLocationManagerDelegate {
private var locationManager: CLLocationManager?
var onDidChangeAuthorization: ((ExampleIntentResponse) -> Void)?
var onDidUpdateLocations: ((ExampleIntentResponse) -> Void)?
func confirm(intent: CurrentSpeedIntent, completion: @escaping (CurrentSpeedIntentResponse) -> Void) {
DispatchQueue.main.async {
self.onDidChangeAuthorization = completion
self.locationManager = CLLocationManager()
self.locationManager?.delegate = self
self.locationManager?.requestWhenInUseAuthorization()
}
}
func handle(intent: CurrentSpeedIntent, completion: @escaping (CurrentSpeedIntentResponse) -> Void) {
DispatchQueue.main.async {
self.onDidUpdateLocations = completion
self.locationManager = CLLocationManager()
self.locationManager?.delegate = self
self.locationManager?.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager?.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedAlways, .authorizedWhenInUse:
let response = ExampleIntentResponse(code: .ready, userActivity: nil)
onDidChangeAuthorization?(response)
default:
let response = ExampleIntentResponse(code: .failure, userActivity: nil)
onDidChangeAuthorization?(response)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else {
return
}
// Do something with the `location` but note that this
// method could be called multiple times by iOS. So if
// you do more that just responding, like fetching a
// photo, or manipulate something in your database you
// will probably set some kind of variable here and
// stop if that is already set.
//
// Example:
// guard intentHandled == false else { return }
// intentHandled = true
//
// The `intentHandled` must of course be a instance variable
// Don't forget to respond!
let response = ExampleIntentResponse(code: .success, userActivity: nil)
self.onDidUpdateLocations?(response)
}
}
这也将仅在实际存在位置时执行。我可以看到,你正在强制展开你的位置,这是一个糟糕的做法,因为它可能是零,然后你的意图就会崩溃。在这里,当我们找到位置时,我们将做我们需要的事情
import Foundation
import CoreLocation
class ExampleIntentHandler: NSObject, ExampleIntentIntentHandling, CLLocationManagerDelegate {
private var locationManager: CLLocationManager?
var onDidChangeAuthorization: ((ExampleIntentResponse) -> Void)?
var onDidUpdateLocations: ((ExampleIntentResponse) -> Void)?
func confirm(intent: CurrentSpeedIntent, completion: @escaping (CurrentSpeedIntentResponse) -> Void) {
DispatchQueue.main.async {
self.onDidChangeAuthorization = completion
self.locationManager = CLLocationManager()
self.locationManager?.delegate = self
self.locationManager?.requestWhenInUseAuthorization()
}
}
func handle(intent: CurrentSpeedIntent, completion: @escaping (CurrentSpeedIntentResponse) -> Void) {
DispatchQueue.main.async {
self.onDidUpdateLocations = completion
self.locationManager = CLLocationManager()
self.locationManager?.delegate = self
self.locationManager?.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager?.startUpdatingLocation()
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .authorizedAlways, .authorizedWhenInUse:
let response = ExampleIntentResponse(code: .ready, userActivity: nil)
onDidChangeAuthorization?(response)
default:
let response = ExampleIntentResponse(code: .failure, userActivity: nil)
onDidChangeAuthorization?(response)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else {
return
}
// Do something with the `location` but note that this
// method could be called multiple times by iOS. So if
// you do more that just responding, like fetching a
// photo, or manipulate something in your database you
// will probably set some kind of variable here and
// stop if that is already set.
//
// Example:
// guard intentHandled == false else { return }
// intentHandled = true
//
// The `intentHandled` must of course be a instance variable
// Don't forget to respond!
let response = ExampleIntentResponse(code: .success, userActivity: nil)
self.onDidUpdateLocations?(response)
}
}
如果尚未完成,则还必须首先在应用程序中请求使用位置。您是否找到了在intent handler中获取用户位置的解决方案?是的,我找到了解决方案。您可以将解决方案发布在此处吗?我也有同样的问题。Thanks@Tongo我确实在下面添加了一个可能对您有所帮助的答案。你能解释一下吗?我仍然无法理解您如何在应用程序中初始化locationManager