Greetings StackOverflow community,
I put a breakpoint on the first line in main(argc, argv) function to see what [NSUserDefaults standardUserDefaults] holds and I was surprised to see that it already had many parameters and values from the application's previous execution.
At what stage are user defaults loaded into memory? Where are they saved once the application terminates?
Thank you!
Sleiman
Related
So I have an array with images that I want to store locally since downloading them each time will take unnecessary effort. I've read that I should NOT store images in NSUserDefaults, which is fine, but I can't for the life of me find any examples on how to store it as a file in a directory that does not change (iOS 8 changed the UUID with each build which creates a new folder each time I run it in Xcode).
I generally have two questions here:
Could someone help me translate this into ObjC? I can't comment on the post since I don't have enough rep...It's the swift part farther down the post that I need help with. Save images in NSUserDefaults?
The other question I have is that it seems to take a lot of time to save the data locally, no matter if it's to file or into the NSUserDefaults. What happens here is that the user of my app closes the app before the data has been stored locally. Is there any way to prevent this? I can add an ActivityIndicator, sure, but I can't seem to find any callback which tells me when the process of saving data has been completed.
Thanks!
So I managed to solve it. The problem was that I simply mixed up the paths. If anyone else wants the translation from Swift to ObjC from the link in the original post here it is:
Write
NSString* relativePath = [NSString stringWithFormat:#"image_%d.jpg", 1];
NSString* realPath = [self documentsPathForFileName:relativePath];
// Write image data to user's folder
[self.ImageData writeToFile:realPath atomically:YES];
// Store path in NSUserDefaults
[defaults setObject:relativePath forKey:#"path"];
Read
NSString *relativePath = [defaults objectForKey:#"path"];
NSString *realPath = [self documentsPathForFileName:relativePath];
self.ImageData = [NSData dataWithContentsOfFile:realPath];
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
First of all I'm using MagicalRecord to manage my Core Data. So right now my database layer works just great and it saves changes every time the change occurs. For example: I'm adding a new entry to a table and it gets written to db file stored on my hard disc right away. What I want to achieve is to keep all the changes in-memory, and write them to db file only on "save" command click.
I figured that the call that does the db file writing is:
[managedObjectContext MR_saveToPersistentStoreAndWait];
So as I figured, I can do all my modifications without calling that method, and then on "save" click, call that method. However, it works only if the thread wasn't changed. Every time, the thread changes the ManagedObjectContext gets reset or recreated, and I lose all my data.
EDIT: just found method in Magical Record:
[NSPersistentStoreCoordinator MR_coordinatorWithInMemoryStore];
which is what I need for the first part of my problem. Although, I don't know how to change from that type of the coordinator to
[NSPersistentStoreCoordinator MR_coordinatorWithSqliteStoreNamed:objectModelName];
without losing any data.
Does anyone know how to do this right?! Any kind of help is really appreciated!
Check these options:
1- There is setupCoreDataStackWithInMemoryStore which might be helpful if you want to run everything in memory.
2-You can save in the background:
[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext){
}];
3-To get the default context or the one for the thread
[NSManagedObjectContext MR_defaultContext];
[NSManagedObjectContext MR_contextForCurrentThread];
I figured it out by doing serious research. I need to use
NSPersistentStoreCoordinator *coordinator = [NSPersistentStoreCoordinator MR_coordinatorWithInMemoryStore];
to have my data "hang" before user clicks on save, where I do the following:
// psc - my current persistentStoreCoordinator; urlForStore - place where I'm gonna store SQLite
[psc migratePersistentStore:[psc persistentStores][0] toURL:urlForStore options:nil withType:NSSQLiteStoreType error:&error];
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
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.