Where is userDefaults saved for SwiftUI Sandbox app?

I have a SwiftUI sandbox app that uses userDefaults.

I would like to verify that the data is correctly saved and also modify it during development to check that my app behaves correctly.

I can see the data in ~/Library/Containers//Data/Library/Preferences/.plist.

My problem is that when I delete this file to check that my app will behave correctly, then it is re-created with old data. It contains entries that I used for development testing, and not in use any longer. I am unable to get a clean file again.

Where is the original data saved, and how do I access it?

I've looked in:

  • ~/Library/Preferences
  • ~/Library/Preferences/By Host
  • ~/Library/Caches
  • ~/Library/Saved Application State

It is not in one of those locations unless it is named differently. Even a search on my mac did not find it.

Accepted Reply

Yes, this is currently for a macOS app where I can see the plist files in finder (or terminal).

In a sandboxed app your preferences get stored within your app’s container. For example, for the app with a bundle ID of com.example.apple-samplecode.Test721805:

  • The container is ~/Library/Containers/com.example.apple-samplecode.Test721805.

  • The preferences file that backs UserDefaults is ~/Library/Containers/com.example.apple-samplecode.Test721805/Data/Library/Preferences/com.example.apple-samplecode.Test721805.plist.

Hence:

% plutil -p ~"/Library/Containers/com.example.apple-samplecode.Test721805/Data/Library/Preferences/com.example.apple-samplecode.Test721805.plist"
{
  "Blobble" => "Blibble"
}

WARNING The location and format of this file is subject to change. It’s fine to poke around in it for debugging purposes, but do not encode such knowledge in your product. Rather, always access user defaults via the UserDefaults API.

There is, however, a much better option, namely the defaults command-line tool. For example:

% defaults read com.example.apple-samplecode.Test721805
{
    Blobble = Blibble;
}

For more info about that tool, see the defaults man page.


and with a TSI that has gone unanswered for two weeks

Hmmmm, that’s not good. Please get in touch with me via email (my address is in my signature). Make sure to reference this thread.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Replies

I have a SwiftUI sandbox app

Are you talking about a macOS app with App Sandbox enabled?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Yes, this is currently for a macOS app where I can see the plist files in finder (or terminal).

Ultimately, I am trying to answer How to preserve state in reference types in swiftUI asked in a different post (and with a TSI that has gone unanswered for two weeks) but I am going down deeper and deeper in to a rabbit hole.

Yes, this is currently for a macOS app where I can see the plist files in finder (or terminal).

In a sandboxed app your preferences get stored within your app’s container. For example, for the app with a bundle ID of com.example.apple-samplecode.Test721805:

  • The container is ~/Library/Containers/com.example.apple-samplecode.Test721805.

  • The preferences file that backs UserDefaults is ~/Library/Containers/com.example.apple-samplecode.Test721805/Data/Library/Preferences/com.example.apple-samplecode.Test721805.plist.

Hence:

% plutil -p ~"/Library/Containers/com.example.apple-samplecode.Test721805/Data/Library/Preferences/com.example.apple-samplecode.Test721805.plist"
{
  "Blobble" => "Blibble"
}

WARNING The location and format of this file is subject to change. It’s fine to poke around in it for debugging purposes, but do not encode such knowledge in your product. Rather, always access user defaults via the UserDefaults API.

There is, however, a much better option, namely the defaults command-line tool. For example:

% defaults read com.example.apple-samplecode.Test721805
{
    Blobble = Blibble;
}

For more info about that tool, see the defaults man page.


and with a TSI that has gone unanswered for two weeks

Hmmmm, that’s not good. Please get in touch with me via email (my address is in my signature). Make sure to reference this thread.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

The preferences file that backs UserDefaults is ~/Library/ ...

Thanks. That is what I've been looking at. The part that confuses me is that I can remove the container, empty my bin, run my app again, and then the file contains data that I did not write with the last run of my app. It contains values that was written by earlier versions of the app. So it seems like it is refreshing the container from some cache that I've not been able to find. Am I seeing ghosts, or do I misunderstand how it should be working?

WARNING The location and format of this file is subject to change. ... but do not encode such knowledge in your product.

Understood. That was my intention - to get a better understanding of what is saved, and to check that it is saved correctly. I was working with arrays of dictionaries where each dictionary had a UUID so making errors in code and debugging without looking at the underlying data was very tricky.

For more info about that tool, see the defaults man page.

I've used the defaults tools. I could see for example that when I removed the container that defaults would show that it no longer sees the data. But just like opening the .plist file in GUI, defaults showed the same stale data returning when I run my app again.

Hmmmm, that’s not good. Please get in touch with me via email

Thanks, will do.

The part that confuses me is that I can remove the container, empty my bin, run my app again, and then the file contains data that I did not write with the last run of my app.

Ah, yeah, that’s not supported. Earlier I wrote “Rather, always access user defaults via the UserDefaults API.” and this is another case of that. You can’t modify this file yourself, and that includes deleting it. This file is managed by a system process, cfprefsd, and it caches a bunch of stuff. If you delete the file, the next time cfprefsd commits a change it’ll overwrite it with the cached contents.

If you want to reset your prefs, use defaults for that as well:

% defaults read com.example.apple-samplecode.Test721805
{
    Blobble = Blibble;
}
% defaults delete com.example.apple-samplecode.Test721805
% defaults read com.example.apple-samplecode.Test721805  
2022-12-15 11:13:21.584 defaults[97490:16834701] 
Domain /Users/quinn/Library/Containers/com.example.apple-samplecode.Test721805/Data/Library/Preferences/com.example.apple-samplecode.Test721805 does not exist
%

That’ll go through cfprefsd and thus everything will remain in sync.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Aaah great, case closed. At least the world makes sense again. I've marked your first reply as correct, as it answered my question but this extra bit of information clears up some confusion that made me think it is not stored there. The full answer may have been that it is stored in ~/Library/Containers but also cached. This may only be useful for development purposes.