deNoww
deNoww

Reputation: 93

macOS - UserDefaults is different in Swift and Terminal

I'm trying to access a system preference (com.apple.menuextra.clock DateFormat specifically) from my Swift app using UserDefaults. Using terminal, defaults read com.apple.menuextra.clock returns

{
    DateFormat = "EEE MMM d  h:mm:ss a";
    FlashDateSeparators = 0;
    IsAnalog = 0;
}

However, if I do this in my Swift app

print(UserDefaults.standard.dictionary(forKey: "com.apple.menuextra.clock"))

I get nil.

How do I access this in Swift? If it helps, I'm only looking for DateFormat so I know if the user prefers 12- or 24-hour time. I've tried

DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: Locale.current)!

then finding whether or not it contains a, but that doesn't work either.

Thanks in advance.

Upvotes: 4

Views: 1381

Answers (2)

deNoww
deNoww

Reputation: 93

To anyone else who has this question in the future: I fixed it by turning off App Sandbox.

Upvotes: 4

Code Different
Code Different

Reputation: 93181

You were not searching in the right domain. When you call dictionary(forKey:), bool(forKey:), integer(forKey:), etc, you are searching through a hierarchy of domains:

  • NSArgumentDomain: the arguments that are passed to your app when it starts.
  • Application domain: the keys that you defined in your app.
  • NSGlobalDomain: system-level preferences.
  • Languages: system-level preferences that are dictated by the user's choice of language.
  • NSRegistrationDomain: temporary keys that your app define. Must be re-registered every time your app launches. If you want it to stick, use the Application Domain.

com.apple.menuextra.clock is not a key in the hierarchy above. It's a domain by itself (think of it as a separate app with its own preferences). Use this instead:

if let dict = UserDefaults.standard.persistentDomain(forName: "com.apple.menuextra.clock") {
    print(dict)
}

Upvotes: 2

Related Questions