Questions about NSUserDefaults - objective-c

I have a couple of questions about NSUserDefaults in Mac OS X:
When does the NSUserDefaults use the dictionary provided by registerDefaults? Only the first time the application is opened or every time the application is opened?
Where is the information from NSUserDefaults stored?
How can I reset NSUSerDefaults?
Thanks!

Only the first time. But you can force an application to reuse the defaults with the terminal.
~/Library/Preferences/YourIdentifier.plist (e.g. com.apple.finder.plist)
Terminal: defaults delete YourIdentifier (e.g. com.apple.finder)
Code: [NSUserDefaults resetStandardUserDefaults];

Actually it should change. I would try it with other controls like NSTextField. When it doesn't work you're doing it wrong
The idea of binding is exactly what you thought it is.

Related

OSX NSUserDefaults not Working

This code gives me always NO in my application. It does indeed work in any other project I copy it... so something must be messed up with my standardUserDefaults, but I absolutely don't know how this can happen and how to solve it!
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool:YES forKey:#"myKey"];
BOOL test = [defaults boolForKey:#"myKey"];
// test is ALWAYS NO here!
Can anybody hint me, where to start or how to get rid of this?
It's a mixed project with swift and objective c and get the same behavior in me AppDelegate.swift, when I put this directly in my applicationDidFinishLaunching
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setBool(true, forKey: "myKey")
let test = defaults.boolForKey("myKey")
// test ALWAYS false here
Before someone asks:
- yes, even with synchronize called between it
- yes this is the whole code, nothing between the lines... set and get it right after does not work
I found a solution, how to fix it, but not why this happens and no clean, good way so far.
If anybody could explain this and give me a better solution, do so!
the problem was:
If you delete the container of a sandboxed app, you also delete the plist for the NSUserDefaults and it's not created again and so NSUserDefaults simply is not working.
the workaround:
As I found here https://ind.ie/labs/blog/app-sandbox-updating-nsuserdefaults-fails-after-deleting-apps-container-directory/ it's a problem with the permanent bookmark of the system.
Well just to empty the trash does not work for me, but what worked: I simply created the missing file!
touch ~/Library/Containers/com.example.myapp/Data/Library/Preferences/com.example.myapp.plist

Storing data in custom keyboard

I am building a custom keyboard that learns the way you type for smarter auto-correct. In order to learn... I need to be able to STORE data to the users device. I've tried using NSFileManager with NSDocumentsDirectory but nothing is getting saved int he AppExtension. (I tested the code (copy paste) in a regular app (non-app-extension) and it worked). I even enabled "Requests Open Access" in the .plist and re-installed the keyboard... still wouldn't save data.
Is there a way to store data in an app-extension?
Possible solutions I've pondered:
•Maybe creating a contact in the users address book that has my info in it (if app-extensions are allowed to do that), but a user might be suspicious as to why my app is requesting permission to modify their contact's address book).
•Displaying a hidden UIWebView that uses javascript injection to store and read data Safari Javascript Database, but I'm afraid this data might be erased if cache is ever cleared.
edit: now this is no longer working for me on iDevice beta 5 (with requestOpenAccess enabled OR disabled)? But it still works on SIMULATOR beta 5? Hmmm
__ original post below: _
It turns out NSUserDefaults DOES save data, it just does not work on BETA 3 simulator, but did work on BETA 5 iDevice. RequestsOpenAccess does NOT need to be enabled!
NSUserDefaults *defaults = [[NSUserDefaults alloc]initWithSuiteName:#"com.company.keyboard.uniqueCodeHere"];//uniqueCodeHere can be anything... we just have to make sure the SuiteName isn't equal to your info.plist bundle ID so we add a random uniqueCode to the end of this ID.
[defaults setObject:#"myStringData" forKey:#"savedStrings"];
[defaults synchronize];
*Note, SuiteName Can NOT equal bundle ID in info.plist or it doesn't work for some reason...

Xcode 5.0 NSUserdefaults still get stored preferences after deleted the plist

I got a problem about programming an osx application on Xcode 5 while using the NSUserDefaults. Usually, we just use [[NSUserDefaults standardUserDefaults] setObject:#"This is an object" forKey:#"Test"] to remember a user preference. After that, the application will generate a plist file at ~/Library/Preferences/application.bundle.identifier.plist.
The problem is, after I deleted the plist file, the application could still get the preferences I stored. There is no way to clear that plist even if I tried to clean project, restart xcode, delete the files in derived folder. The only way for me to solve this problem is to restart the system, so I guess there is something stored in the memory. The question is how can I clear these stored preferences? (I don't think it's convenient to clear the preferences by adding code manually in debugging and testing.) And I tried the former version of Xcode 4.x, there's no such problem. Anyone has interest could just create a new cocoa project, and add the code like:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:#"This is an object." forKey:#"Test"];
NSLog(#"%#", [defaults objectForKey:#"Test"]);
under "applicationDidFinishLaunching". Then go and delete ~/Library/Preferences/application.bundle.identifier.plist.
After that, comment the line: [defaults setObject:#"This is an object." forKey:#"Test"];
in your code and run the application again. The console will still show "This is an object."
My environment is Mavericks GM and Xcode 5.0(5a1413).
Hope this is not something just only happened to me and appreciated any help!
This is an OS X issue not directly related to the version of Xcode you are using. Apple's official line is that deleting the plist file to remove preferences has never been officially supported, and in more recent OS X releases it is unreliable due to changes in the way the preferences are stored.
The supported way to remove preferences is to use the defaults command at the terminal, e.g.:
defaults delete application.bundle.identifier
The defaults command can also remove/change individual settings with in the preferences. For full details see man defaults.

Detect First Time User

How can I detect if the user has just downloaded the application and opened it for the first time? IS this a NSUserDefaults? I want to be able to show a welcome screen only the first time my application is run.
Thanks
check for a bool in NSUserDefaults and if it is not set do whatever you want and save a YES-bool back to NSUserDefaults. If you show an alert you probably should put the setBool:forKey: in the delegate method which is called after you have dismissed the alert.
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"wasLaunchedBefore"]) {
NSLog(#"First launch");
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"wasLaunchedBefore"];
}
You can use the NSUSerDefaults.By this when the user opened app check whether there is any values in your user defaults for a key.If it is not then that is first time.After this check you have to update the value for the key which you have checked previously.
You can check if flag is set in NSPreferences or check if file exists in app's file (file that you create after the first launch).
You need to set in your application if opened first time then show that stuff which you want to show first time. There is no any other way to find out that user downloaded your application and he run it or not. On run process you need to set it inside your application.
If you use NSUserDefaults then user can reinstall your application. And application will think thank user use it for first time again. But after updating application remembers that the user has already launched it.
I can't understand from your question if it is appropriate for you but the most of applications work this way

Where is a Mac Application's NSUserDefaults Data Stored?

I am using NSUserDefaults to store some data in my application.
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:#"dummy string" forKey:#"lastValue"];
[prefs synchronize];
For testing purposes I need to see the System Preferences plist file where my NSUserDefaults data is saving on the Mac.
I know where the iOS application user defaults are stored, but I don't know about mac application. Where is a Mac Application's NSUserDefaults Data Stored?
They can be found in more than one place:
~/Library/Preferences/com.example.myapp.plist
~/Library/SyncedPreferences/com.example.myapp.plist
and if sandboxed
~/Library/Containers/com.example.myapp/Data/Library/Preferences/com.example.myapp.plist
~/Library/Containers/com.example.myapp/Data/Library/SyncedPreferences/com.example.myapp.plist
In ~/Library/Preferences/com.example.myapp.plist.
(Xcode 7.3.1,macOS 10.11.6)
For Additional,if you are using App Groups
if let prefs = NSUserDefaults(suiteName: "group.groupApps") {
...
}
plist file will be here:
~/Library/Group Containers/group. groupApps/Library/Preferences/group.groupApps.plist
On Sierra, I found the data here: ~/Library/Application Support/.
One more possible location for these data comes into play when trying things out in a Playground. I was experimenting with UserDefaults in a Playground, using XCode 8.3 and Swift 3, and wanted to see the resulting plist file. After some detective work (UserDefaults files have the bundle identifier in the filename and calling Bundle.main.bundleIdentifier in a Playground gives the XCode identifier) I found to my great surprise that the UserDefaults data was added to:
~/Library/Preferences/com.apple.dt.Xcode
In other words, keys and values are added to the XCode preferences file! I double-checked by coming up with very unlikely strings for the keys and they were indeed added there. I did not have the courage to try using some keys that were already in use by XCode but caution seems good here.