如何使用 AppleScript 告诉我的设备当前与某个位置的距离?

How can I tell my devices current distance from a location using AppleScript?

基于此解决方案:,我正在尝试使用 CLLocation 的距离方法创建一个简单的地理围栏脚本(根据与特定位置的距离设置我的状态)。

我不是 AppleScript 专业人士,所以我在思考如何在脚本中初始化 CLLocation 对象(带有纬度和经度)以与原始答案脚本返回的我的当前位置进行比较。

所以我正在寻找这样的东西,其中 myCurrentLocation 是从原始脚本返回的位置对象(显然是错误的,只是一些伪 obj-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❯

其实你已经不远了:

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

其中 my locationCLLocation 的实例。因此,在原始脚本中,而不是:

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

你想要:

set my result to item 1 in locations

因为 locations 应该是 CLLocation 值的 NSArray

但是,自从编写该脚本后,CLLocationManager class 中添加了一个新的实例方法,即 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❯

我还没有测试这个脚本,因为我在 High Sierra,它需要 Mojave 或更高版本。我会在某个时候重新启动到 Catalina 并检查它是否有错误。