0

MacOS 13.2.1, Xcode 14.2

I'm struggling to get CLLocation to work on Ventura from a command line executable. It works fine from a GUI app. I have the same experience with Swift and Objective C (using the app template works but command line tool doesn't); I'm using ObjC for the example below.

I found some example code online that I've put into two Xcode projects at https://github.com/n8henrie/test-location.

  • location-objc-app was created with the Xcode -> new project -> macos -> app template (using storyboard and objective c)
  • location-objc was created with the Xcode -> new project -> macos -> Command Line Tool template (objective c)

When I run it in Xcode, location-objc does not prompt for any permissions, and can't retrieve the location:

2023-03-18 09:30:50.109158-0600 location-objc[92344:8383074] authorization status: 0
2023-03-18 09:30:52.121832-0600 location-objc[92344:8383074] status: 1
2023-03-18 09:30:52.121868-0600 location-objc[92344:8383074] 0.000000.0.000000
Program ended with exit code: 0

location-objc-app does give me a popup for permissions and successfully prints the location:

2023-03-18 09:30:56.815837-0600 location-objc-app[92346:8383607] authorization status: 0
2023-03-18 09:30:56.823216-0600 location-objc-app[92346:8383607] status: 0
2023-03-18 09:30:56.823263-0600 location-objc-app[92346:8383607] 12.REDACTED.-34.REDACTED

I've ensured that the resulting location-objc binary has the Info.plist information embedded:

$ otool -P location-objc 
location-objc:
(__TEXT,__info_plist) section
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>BuildMachineOSBuild</key>
    <string>22D68</string>
    <key>CFBundleExecutable</key>
    <string>location-objc</string>
    <key>CFBundleIdentifier</key>
    <string>com.n8henrie.location-objc</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>location-objc</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0</string>
    <key>CFBundleSupportedPlatforms</key>
    <array>
        <string>MacOSX</string>
    </array>
    <key>CFBundleVersion</key>
    <string>1</string>
    <key>DTCompiler</key>
    <string>com.apple.compilers.llvm.clang.1_0</string>
    <key>DTPlatformBuild</key>
    <string>14C18</string>
    <key>DTPlatformName</key>
    <string>macosx</string>
    <key>DTPlatformVersion</key>
    <string>13.1</string>
    <key>DTSDKBuild</key>
    <string>22C55</string>
    <key>DTSDKName</key>
    <string>macosx13.1</string>
    <key>DTXcode</key>
    <string>1420</string>
    <key>DTXcodeBuild</key>
    <string>14C18</string>
    <key>LSMinimumSystemVersion</key>
    <string>13.1</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>Always and When!</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>Always!</string>
    <key>NSLocationUsageDescription</key>
    <string>General!</string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>When in use</string>
</dict>
</plist>

and it seems to have appropriate entitlements:

$ codesign -dvv --entitlements - location-objc 
Executable=/Users/n8henrie/Library/Developer/Xcode/DerivedData/location-objc-gxafbuxirpiqouanzeqrgitsgzss/Build/Products/Debug/location-objc
Identifier=com.n8henrie.location-objc
Format=Mach-O thin (arm64)
CodeDirectory v=20500 size=795 flags=0x10002(adhoc,runtime) hashes=14+7 location=embedded
Signature=adhoc
Info.plist entries=21
TeamIdentifier=not set
Runtime Version=13.1.0
Sealed Resources=none
Internal requirements count=0 size=12
[Dict]
    [Key] com.apple.security.app-sandbox
    [Value]
        [Bool] true
    [Key] com.apple.security.files.user-selected.read-only
    [Value]
        [Bool] true
    [Key] com.apple.security.get-task-allow
    [Value]
        [Bool] true
    [Key] com.apple.security.personal-information.location
    [Value]
        [Bool] true

I've tried every combination I can think of enabling and disabling the sandbox, hardened runtime, manually re-codesigning (with numerous combinations of the below flags):

$ codesign --sign - --force --deep --strict --timestamp --options runtime --entitlements entitlements.plist --identifier com.n8henrie.location-objc ./location-objc 
./location-objc: replacing existing signature
$ ./location-objc 
2023-03-18 09:40:34.517 location-objc[96782:8398475] authorization status: 0
2023-03-18 09:40:36.527 location-objc[96782:8398475] status: 1
2023-03-18 09:40:36.527 location-objc[96782:8398475] 0.000000.0.000000

I've tried manually opening the executable from Finder, hoping that would give me the permissions popup, but no matter what I try it doesn't work.

In console, locationd looks like it's trying to prompt me:

{"msg":"Showing #AuthPrompt", "requestType":5, "client":"92F5C54E-CAEB-44A5-AF60-85E44A017BD2:com.n8henrie.location-objc"}
{"msg":"#AuthPrompt AuthorizationRequest completion", "ClientKey":"92F5C54E-CAEB-44A5-AF60-85E44A017BD2:com.n8henrie.location-objc", "RequestType":"CLClientManager_Type::AuthorizationRequestTypeLegacyAlways"}
{"msg":"#AuthPrompt sending message to #CoreLocationAgent", "MessageDict":"{\n    bundleid = \"com.n8henrie.location-objc\";\n    isMarzipan = 0;\n    isMasquerading = 0;\n    pid = 97813;\n    uuid = \"09278F43-651E-4E29-9E34-0AC87F7ABE35\";\n}", "Connection":"\/System\/Library\/CoreServices\/CoreLocationAgent.app\/Contents\/MacOS\/CoreLocationAgent", "User":"92F5C54E-CAEB-44A5-AF60-85E44A017BD2"}
client '[92F5C54E-CAEB-44A5-AF60-85E44A017BD2]com.n8henrie.location-objc' not authorized for location; not starting yet
{"msg":"client not currently authorized for location; sending error", "client":"[92F5C54E-CAEB-44A5-AF60-85E44A017BD2]com.n8henrie.location-objc"}

but nothing ever shows.

How can I get a standalone CLI executable to use CLLocation? I do not consider using Shortcuts.app to be a reasonable workaround in this case, though users looking for a "quick and dirty" solution might take this approach.

Sidenote:

This was originally asked on AskDifferent but closed as off-topic (with a recommendation to post at SO) based on their rules, though I had thought this fell under their specific example of Xcode for non-language specific tasks (as I think the issue is with permissions, codesigning, sandboxing, etc and not swift or objc).

Code-level programming questions (cocoa, LLVM, etc…) are off-topic here. We do encourage AppleScript, Automator, and UNIX shell scripting questions as well as how to use tools like Xcode for non-language specific tasks.

EDIT: I've added an additional Xcode project to the example repo: https://github.com/n8henrie/test-location/tree/master/test-location-app-makefile. This one is in Swift and uses a Makefile to build (instead of Xcode). It seems to show the same issue -- as is, if I create an app folder structure (test-location.app/Contents/MacOS/test-location), include an Info.plist, and codesign with --entitlements (even if the entitlements.plist is empty), it works. However, if I don't put the same binary into an app folder / structure, the bare binary doesn't work.

So it doesn't seem to be any special sauce that Xcode is doing.

n8henrie
  • 2,737
  • 3
  • 29
  • 45
  • 2
    It's likely you need to setup and run a runloop to get callbacks from the location framework. This is done for you in a GUI app but not CLI. See [here](https://stackoverflow.com/questions/42634584/corebluetooth-on-mac-command-line-application/42635036#42635036) – TheNextman Mar 19 '23 at 16:29
  • And the comments on that question/answer link a [specific solution](https://gist.github.com/cmittendorf/2c6eefc6dd128b323428) for your problem. – TheNextman Mar 19 '23 at 16:30
  • @TheNextman thanks for the suggestion! I'll look into it. So far the `LocateMe.swift` file is not prompting me for permissions access either, but I'll try to adapt my CLLocation code to see if it does. If I can get it working I'll gladly accept this as a solution! – n8henrie Mar 19 '23 at 20:14
  • Maybe take a look at [this project](https://github.com/fulldecent/corelocationcli) also – TheNextman Mar 19 '23 at 22:05
  • 1
    @TheNextman https://github.com/fulldecent/corelocationcli/issues/48#issuecomment-1474512866 – n8henrie Mar 20 '23 at 02:20
  • @TheNextman no dice, adding a runloop doesn't seem to change anything. – n8henrie Mar 20 '23 at 18:56
  • @n8henrie If adding a runloop doesn't seem to change anything, then why did you [post an answer](https://stackoverflow.com/a/75795467/20287183) stating that adding `RunLoop.main.run()` allowed you to get the location permission? – HangarRash Mar 22 '23 at 00:02
  • @TheNextman thank you! I wrote "location" when I meant "calendar," which is what that question was about; I have since corrected the mistake. I still have not gotten this to work for location with CLI tool (but it works for both camera and calendar access). – n8henrie Mar 22 '23 at 13:30

0 Answers0