SwiftData PersistentIdentifier saved to UserDefaults?

Hi,

I'm updating my app from CoreData to SwiftData and came across an issue. My app has multiple users so in CoreData and I assigned each a myID value set to an UUID so I could use UserDefaults to set the preferred user on app load. When switching over I noticed the PersistentIdentifier value and got excited as I could fetch the matching entity with modelContext.model(for: yourID). I decided to use that instead so I updated my UserDefaults code from UUID to this:

    @Published var selectedUserID: PersistentIdentifier? {
        didSet {
            UserDefaults.standard.set(selectedUserID, forKey: "selectedUserID")
        }
    }

    init() {
        self.selectedUserID = UserDefaults.standard.object(forKey: "selectedUserID") as? PersistentIdentifier ?? nil
    }

This code compiles and, of course the id is currently set to nil. My issue now is when I try to assign a user to it ar my app crashes and I get the following error:

Attempt to set a non-property-list object SwiftData.PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://6FE80FC9-0B4C-491E-8093-DED37A619F1B/EnteredUser/p834), implementation: SwiftData.PersistentIdentifierImplementation) as an NSUserDefaults/CFPreferences value for key selectedUserID

Should I go back to an additional UUID field in my user model and find it that way or is there a way to use the PersistentIdentifier value with my UserDefaults?

Thanks for any tips.

If you're already using SwiftData, why rely on userdefaults? Store the last user in a swift data model and fetch it from there instead.

I hadn't thought of using it as a singleton.... may switch to that Thanks.

To answer your original question, you can only save certain elements in UserDefaults, and a PersistentIdentifier is not one of them. This type does implement the Codable protocol, so you can use something like JSON encoding/decoding to save to and restore from UserDefaults.

func saveValue(_ newValue: PersistentIdentifier, to store: UserDefaults, at key: String) {
  let encoder = JSONEncoder()
  store.setValue(try! encoder.encode(newValue), forKey: key)
}

func restoreValue(from store: UserDefaults, at key: String) -> PersistentIdentifier? {
  guard let raw = store.data(forKey: key) else {
    return nil
  }
  let decoder = JSONDecoder()
  return try? decoder.decode(PersistentIdentifier.self, from: raw)
}

Instead of using UserDefaults to save the PersistentIdentifier, you might want to use AppStorage. https://developer.apple.com/documentation/swiftui/appstorage/init(_:store:)-9lku2

@Model class Recipe { ... }
struct RecipeList: View {
    @Query var recipes: [Recipe]
    @AppStorage("selectedID") var selectedRecipeID: Recipe.ID?

    var body: some View {
        List(recipes, selection: $selectedRecipeID) { recipe in
            RecipeDetail(recipe)
        }
    }
}

or

let selectedRecipeID = AppStorage<PersistentIdentifier?>("selectedID").wrappedValue
SwiftData PersistentIdentifier saved to UserDefaults?
 
 
Q