MacOS Sonoma has a new privacy/security feature. If an app tries to access data in another app’s container, it triggers a warning message. You can customize the error message by setting a plist in your app bundle. See NSAppDataUsageDescription for details.
My question: how can a Xojo app detect when the user has denied permission?
The code below, when run on Sonoma, always returns “Success”, regardless of whether the user grants or denies permission.
The only difference is that if the user denies permission, the plist is not written to the container. However, it appears as if CFPreferences is caching the data in RAM, so from the app’s point of view the write/read is successful.
dim key as string = "foobar" dim value as string = "success" + str(Microseconds,"#") dim result as string = "failure" dim f as FolderItem = SpecialFolder.UserLibrary dim path as string = f.ShellPath + "/Containers/com.apple.ScreenSaver.Engine.legacyScreenSaver.x86-64/Data/Library/Preferences/" dim bundleID as string = "com.myapp.xyz" dim cfp as new CFPreferencesMBS dim cfbundleID as CFStringMBS = New CFStringMBS(path + bundleID) dim cfkey as New CFStringMBS(key) dim cfvalue as new CFStringMBS(value) // try to set the value, this will trigger the NSAppDataUsageDescription warning cfp.SetValue(cfkey,cfvalue,cfbundleID,cfp.kCFPreferencesCurrentUser, cfp.kCFPreferencesAnyHost) // this always succeds, even if the user denies permission if not cfp.AppSynchronize(bundleID) then MsgBox "syncrhonize failed" end if // get a new CFPreferencesMBS object cfp = nil cfp = new CFPreferencesMBS dim o as CFObjectMBS = cfp.CopyValue(cfkey, cfbundleID, cfp.kCFPreferencesCurrentUser, cfp.kCFPreferencesAnyHost) if o isa CFStringMBS then dim t as CFStringMBS=CFStringMBS(o) if t <> nil then result = t.str end if end if if result = value then MsgBox "Success! value=" + value else MsgBox "Failure! value=" + value end if