Why does NSUserDefaults leave temporary plist files in Library / Preferences for my application?

I find it difficult to understand why NSUserDefaults leaves junk file files in the library / Preferences for my application.

I see the following files ...

 com.mycompany.myapp.plist com.mycompany.myapp.plist.3gaPYul com.mycompany.myapp.plist.c97yxEH 

... etc. The plist.* Files are 0 bytes. It seems that every time the application starts, it leaves a new one. I made sure that I did not call at all -[NSUserDefaults synchronize] , but if I call him, it speeds up the appearance of unwanted files for this run. Going into the debugger, as soon as I go to the call for synchronization, a new file appeared. If I take out a synchronization call, a new spam file sometimes appears when the application starts, and sometimes when the application closes.

I also check to see if it’s possible that I am setting the default user in the stream (unlikely, but possibly possible), thought the docs say it is thread safe.

Any help is appreciated. Thanks!

EDIT:

Just found this: CFPreferences creates multiple files

While I agree with the idea of ​​the defendants, he does not explain β€œwhy?”. part.

+7
source share
3 answers

I made sure that this is Apple's mistake, but I could not create a small sample to illustrate this. I got a ton of reviews that say this about Apple. Since I kind of hit the wall and I need to move, I ended up making an unpleasant hack, shown below.

 @implementation NSUserDefaults(Hack) - (BOOL)synchronize { BOOL result = CFPreferencesAppSynchronize((CFStringRef)[[NSBundle mainBundle] bundleIdentifier]); if (!result) { // there probably a temp file lingering around... try again. result = CFPreferencesAppSynchronize((CFStringRef)[[NSBundle mainBundle] bundleIdentifier]); // regardless of the result, lets clean up any temp files hanging around.. NSFileManager *fileManager = [NSFileManager defaultManager]; NSString *prefsDir = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Preferences"]; NSDirectoryEnumerator *dirEnumerator = [fileManager enumeratorAtPath:prefsDir]; NSString *file = nil; NSString *match = [[[NSBundle mainBundle] bundleIdentifier] stringByAppendingString:@".plist."]; while ((file = [dirEnumerator nextObject])) { if ([file rangeOfString:match].location != NSNotFound) { NSString *fileToRemove = [prefsDir stringByAppendingPathComponent:file]; [fileManager removeItemAtPath:fileToRemove error:nil]; } } } return result; } 
+3
source

Are these plist files saved between application launches? Do you have errors while saving your preferences? Does your official plist support write permissions?

Lists of properties can be written atomically, which means that they are first written to a temporary file, and if there is no error during the write operation, the temporary file is renamed to the original file name. Under normal circumstances, you should not see temporary files.

+1
source

Thought - are the data you are writing stored in a properly named file? I think you meant that it was. I am wondering if the correctly named file with write permissions is opened with something other than NSDefaults, and if this blocks the safe copy of the save from the temporary file phase?

+1
source

All Articles