UserDefaults.standard.set() shows warning, but it can not be acted upon?

We run simple iOS Swift code triggered by a remote notification:

UserDefaults.standard.set("key", forKey: "value")

It runs fine when the app is active or inactive, but when the device is closed/locked and the code is triggered, we see a warning in Xcode:

Couldn't write values for keys (
    key
) in CFPrefsPlistSource<0x3018802d0> (Domain: com.example, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents Need Refresh: No): Path not accessible
Not updating lastKnownShmemState in CFPrefsPlistSource<0x3018802d0> (Domain: com.example, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents Need Refresh: No): 767 -> 767

The issue is that there seems to be no way to catch that warning. The value is set, when it's re-read the value is correct. But the value is never written to disk, so after an app restart/update the value is gone, potentially has an old wrong value.

This code runs without any interruption, it's just showing the warning on iOS 17.7.1 on iPad:

    UserDefaults.standard.set("key", forKey: "value")
    UserDefaults.standard.synchronize()
    print("value: \(UserDefaults.standard.string(forKey: "key"))")

Should there not be a way to catch this, so the code can act accordingly to the circumstances? It would be good to know inside the code that the value is not persisted. I would expect that an exception is generated somewhere which can be caught.

It seems .completeFileProtectionUntilFirstUserAuthentication enables files to be written to disk while the device is closed/locked, can something similar be used for UserDefaults.standard?

Answered by DTS Engineer in 814635022

My general advice on this front is: If you want to work with important data from the background, store that data in a file whose data protection you control.

So, rather than using UserDefaults for this, create your own settings file and set its data protection to match your background execution requirements.

Share and Enjoy

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

Accepted Answer

My general advice on this front is: If you want to work with important data from the background, store that data in a file whose data protection you control.

So, rather than using UserDefaults for this, create your own settings file and set its data protection to match your background execution requirements.

Share and Enjoy

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

UserDefaults.standard.set() shows warning, but it can not be acted upon?
 
 
Q