Как узнать текущее расстояние до устройства с помощью AppleScript? - PullRequest
0 голосов
/ 16 марта 2020

Основываясь на этом решении: AppleScript - Geographi c Местоположение , я пытаюсь использовать метод расстояния CLLocation для создания простого сценария гео-фехтования (настройка моего статуса на основе расстояния от определенных мест) .

Я не профессионал AppleScript, поэтому я борюсь с концепцией инициализации объекта CLLocation в скрипте (с широтой и долготой) для сравнения с моим текущим местоположением, возвращаемым исходным ответом. скрипт.

Итак, я ищу что-то вроде этого, где myCurrentLocation - это объект местоположения, возвращаемый из исходного сценария (очевидно, неверный, просто некоторые псевдообъекты c):

set tagetLatitude to "50.850206"
set targetLongitude to "5.690947"
set targetLocation to CLLocation's initWithLatitude:tagetLatitude longitude:targetLongitude

set distance to targetLocation's distance:myCurrentLocation
return distance

Это оригинальный скрипт CJK для справки:

use framework "CoreLocation"
use framework "Foundation"
use scripting additions

property this : a reference to the current application
property nil : a reference to missing value
property _1 : a reference to reference

property CLLocationManager : a reference to CLLocationManager of this
property kCLLocationAccuracyThreeKilometers : a reference to 3000.0
--------------------------------------------------------------------------------
property running : false
property result : missing value -- Lat./long. or error description
property number : 0 -- Error code
property seconds : 10 -- Maximum time to allow script to run
--------------------------------------------------------------------------------
# IMPLEMENTATION:
my performSelectorOnMainThread:"getLocation" withObject:nil waitUntilDone:true
return my result
--------------------------------------------------------------------------------
# HANDLERS & SCRIPT OBJECTS:
to getLocation()
    set locationManager to CLLocationManager's new()

    locationManager's setDelegate:me
    locationManager's setDesiredAccuracy:kCLLocationAccuracyThreeKilometers

    set my running to true
    set started to current date

    locationManager's startUpdatingLocation()

    repeat while my running
        delay 0.5
        if (current date) - started > my seconds then exit repeat
    end repeat
end getLocation

on locationManager:locationManager didUpdateLocations:locations
    local locationManager, locations

    locationManager's stopUpdatingLocation()

    set my running to false
    set my result to (locations's valueForKey:"coordinate") as record
end locationManager:didUpdateLocations:

on locationManager:locationManager didFailWithError:err
    local locationManager, err

    tell err's code()
        set my number to it
        set my result to item (it + 1) in my enum's kCLError
        if it ≠ 0 then set my running to false
    end tell
end locationManager:didFailWithError:

script enum
    property kCLError : {¬
        "Location Unknown", ¬
        "Denied", ¬
        "Network", ¬
        "Heading Failure", ¬
        "Region Monitoring Denied", ¬
        "Region Monitoring Failure", ¬
        "Region Monitoring Setup Delayed", ¬
        "Region Monitoring Response Delayed", ¬
        "Geocode Found No Result", ¬
        "Geocode Found Partial Result", ¬
        "Geocode Canceled", ¬
        "Deferred Failed", ¬
        "Deferred Not Updating Location", ¬
        "Deferred Accuracy Too Low", ¬
        "Deferred Distance Filtered", ¬
        "Deferred Canceled", ¬
        "Ranging Unavailable", ¬
        "Ranging Failure"}
    property CLAuthorizationStatus : {¬
        "Not Determined", ¬
        "Restricted", ¬
        "Denied", ¬
        "Authorized (Always)", ¬
        "Authorized When In Use"}
end script
---------------------------------------------------------------------------❮END❯

1 Ответ

1 голос
/ 17 марта 2020

Вы на самом деле не за горами:

on distance to {latitude:|?|, longitude:|λ|}
        ((my location)'s distanceFromLocation:(CLLocation's ¬
                alloc()'s initWithLatitude:|?| longitude:|λ|)) ¬
                as real
end distance

, где my location - это экземпляр CLLocation. Поэтому в исходном сценарии вместо:

set my result to (locations's valueForKey:"coordinate")

вы хотите:

set my result to item 1 in locations

, поскольку locations должно быть NSArray из CLLocation значения.

Однако с момента написания этого скрипта в класс CLLocationManager был добавлен новый метод экземпляра, а именно requestLocation()

Таким образом, сценарий, вероятно, можно немного сократить примерно до следующего:

--------------------------------------------------------------------------------
use framework "Foundation"
use framework "CoreLocation"
--------------------------------------------------------------------------------
property this : a reference to current application
property nil : a reference to missing value

property CLLocation : a reference to CLLocation of this
property CLLocationManager : a reference to CLLocationManager of this
--------------------------------------------------------------------------------
property location : []
--------------------------------------------------------------------------------
# IMPLEMENTATION:
my performSelectorOnMainThread:"findMe" withObject:nil waitUntilDone:yes
return the distance to {latitude:-90.0, longitude:0.0}

to findMe()
        tell CLLocationManager's new()
                setDelegate_(me)
                setDesiredAccuracy_(3000.0)
                requestLocation()
        end tell

        repeat until my location ≠ []
                delay 1
        end repeat
end findMe
--------------------------------------------------------------------------------
# MAIN HANDLERS:
on distance from A as {record, reference} : [] to B as {record, reference}
        local A, B

        if A = [] then set A to my location
        if A's class = record then
                set {latitude:|?|, longitude:|λ|} to A
                tell CLLocation's alloc() to set A to ¬
                        initWithLatitude_longitude_(|?|, |λ|)
        end if
        if B's class = record then
                set {latitude:|?|, longitude:|λ|} to B
                tell CLLocation's alloc() to set B to ¬
                        initWithLatitude_longitude_(|?|, |λ|)
        end if

        (B's distanceFromLocation:A) as meters as kilometers
end distance
--------------------------------------------------------------------------------
# DELEGATED HANDLERS:
on locationManager:[] didUpdateLocations:here
        set [my location] to here
end locationManager:didUpdateLocations:

on locationManager:[] didFailWithError:E
        error E's localizedDescription() as text
end locationManager:didFailWithError:
---------------------------------------------------------------------------❮END❯

Я еще не тестировал этот сценарий, так как я нахожусь в Высокой Сьерре, и это требует Мохаве или позже. Я перезагружусь в Catalina в какой-то момент и проверю его на ошибки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...