【问题标题】:Access user current location in custom Sirikit intends, iOS, swift在自定义 Sirikit 意图、iOS、swift 中访问用户当前位置
【发布时间】:2019-07-18 18:46:57
【问题描述】:

我创建了一个自定义 Sirikit 意图,在 IntentHandler 类中我找不到默认设置位置隐私“始终”的用户位置。 请看代码。

    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"))
        }
    }
}
}

如果我评论位置管理器,它会崩溃。

【问题讨论】:

  • 您是否找到了在意图处理程序中获取用户位置的解决方案?
  • 是的,我找到了解决方案。
  • 你能在这里发布解决方案吗?我有同样的问题。谢谢
  • @Tongo 我确实在下面添加了一个可能对您有所帮助的答案。 stackoverflow.com/a/59585774/1322262

标签: ios swift ios12 sirikit


【解决方案1】:
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"))
    }}
}

【讨论】:

  • 您能详细解释一下吗?我还是不明白你是怎么在意图中初始化locationManager的
【解决方案2】:

TLDR:在主线程中创建CLLocationManager,它应该可以工作


如果您在 Mac 上打开 Console.app 并监控正在运行 Siri Intent 的设备,您可能会看到类似以下的消息:

位置管理器 (0xe86bdf0) 在主线程以外的线程上执行的调度队列上创建。

(就像在这个问题中一样:location manager was created on a dispatch queue。)

问题是核心位置必须在附加到主循环的运行循环中创建。最简单的解决方案是在主循环中创建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)
    }
}

这也将仅在实际存在位置时执行。我可以看到您正在强制解开您的位置,这是一种不好的做法,因为它可能为零,然后您的意图就会崩溃。在这里,我们将在获得位置后做我们需要的事情。

如果尚未完成,也必须先在应用中提出使用位置的请求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多