Force 'Shared User Defaults Controller' to save to disk immediately? - objective-c

I have a preferences pane that uses the Shared User Defaults Controller, which reading and saving preferences a piece of cake. It seems though that when changes are made to the fields, they aren't immediately saved to the plist fie. This creates a problem when my application needs to re-read the file immediately after the change has been made and the plist still hasn't been updated.
How can I force the preferences pane to update the preferences file immediately?

This will automatically save any change you do right away to disk:
NSUserDefaultsController *controller = [NSUserDefaultsController sharedUserDefaultsController];
[controller setAppliesImmediately:YES];
If you need this only in specific cases, you can also use and save some of the expensive I/O (you really should try to let the cache mechanism cache as much as possible instead of writing everything right away to disk):
NSUserDefaultsController *controller = [NSUserDefaultsController sharedUserDefaultsController];
[controller save:self];
Also, are you sure that you are trying to solve the right problem? You can always get the up to date version of the user defaults by querying NSUserDefaults where you don't need to care about wether the current version is cached in RAM or already written to disk.

Per the docs:
[userDefaults save:self];
or
[userDefaults setAppliesImmediately:YES];

Related

Where does file store for [NSTableView setAutosaveName]?

After manually creating NSTableView columns, I have called
[self.tableView setAutosaveName:#"MyTable"] and [self.tableView setAutosaveTableColumns:YES]
Ok, it works.
After closing the App I have a file ~/Library/Preferences/MyApp.plist and it has my table settings.
I delete this file and relaunch App and I have seen changed position and size of columns. Not default!
I have tried find where this settings were stored but nothing.
Help me please!
There's a server process, cfprefsd, that caches and serves the user defaults. Apps communicate with that. They don't directly access the file. It has never been reliable to directly manipulate the file as a means of changing the defaults.
To manipulate the user defaults, you must either use the CFPreferences or NSUserDefaults APIs programmatically or, from a command line, use the defaults program. For example:
defaults delete com.yourdomain.yourapp

How to keep database changes in-memory before storing them to file on save call?

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];

Objective c - Core Data saving approach

I have some NSManagedObject subclass in my app, and I'm trying to understand when and how to save changes.
I will try to explain myself, for example class A is NSManagedObject subclass.
During app life cycle I do:
App launched
...
Create an instance of class A
...
Change some properties of A instance
...
App go to background
...
App becomes active again
...
Change some more properties of A instance
...
App terminates
When do I need to call [context save:] ??
Do I call it after every change in A instance? Or maybe I call it only when app go to background?
Should I call it after creation or deletion of any A instance?
A nice approach is place UIManagedDocument in your AppDelegate. Then you can call [context save] whenever some change occurs in the app (like a crash). The order I like to follow is something like:
Create UIManagedDocument object (in application did load or wherever)
and assign it to a property
Setup the document (check whether it exist on disk or is already open, etc.. and respond accordingly)
Pass the UIManagedObjectContext to the initial UIViewController in your app (from there you can pass the context to other view controllers)
UIManaged document will save the context for you.
Take a look at the UIManagedDocument documentation to configure persistent store options (you send an NSDictionary of options to your UIManagedDocument instance, see the first example through the link below).
UIManagedDocument documentation:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIManagedDocument_Class/Reference/Reference.html
Also see the CoreData lecture and demo (lectures 13 and 14) of the iPhone and iPad application development course with Paul Hegarty available free on iTunesU (Fall 2011).
The data will not be saved to the persistent store until you call save. So, it depends on what you want in your app. If you want it to be able to recover the last value it ever had, then you should save after each modification.
Easy change is to just save after making modifications.
You could do something a bit more fancy, like only save after some set amount of time, so many changes are grouped together... and catch any event that will put your app in the background and then save...
But, that's what UIManagedDocument does automatically for you, so you could just use that instead.
Depending on the amount of changes that you make and the volume of data that needs to be saved with each change, yo can choose to save a little or a lot. If you are just saving a string or a number or a bool, then go ahead and call save: on your context as soon as the changes were made.
If it is a lot of data, you may want to coalasce your changes and then save it on a background queue so that you are not blocking the main queue. This way you are not waiting to go to the background to perform your saves.
Tim

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

Core data/NSPersistentDocument marking file "clean" every time any field finishes editing

I'm working with a document-based core-data OS X application. The problem I'm having is that whenever I edit any field on the document, after I press tab or click to something else (i.e. I finish editing/change focus), the document is marked as clean and undo is reset. When I try to save the file, however, the resulting document opens without the data I entered. What might be the problem, or, any pointers on where to look to fix this? Here's some stuff I know and things I've already tried:
I know it's not somehow saving because it never stops at the breakpoint in my overridden writeSafelyToURL:(NSURL *)inAbsoluteURL ofType:(NSString *)inTypeName forSaveOperation:(NSSaveOperationType)inSaveOperation error:(NSError **)outError and it also never sends an NSManagedObjectContextDidSaveNotification.
The documents are packaged in an NSFileWrapper directory with the core data store inside (and also some other files). I access the entities through an NSObjectController and a couple NSArrayControllers. It happens with both core data properties and manually registered changes in the rest of the file wrapper.
Update: At the suggestion of Martin, I tried NSUndoManager's notifications, and all I can seem to glean from it is that more than one undo manager is in play. If I add an observer for NSUndoManager, it won't post if I specify an object, and then if I don't, the notification object is not equal to [self undoManager]. I added updateChangeCount to my category on NSPersistentDocument, and it never gets called. setDocumentEdited basically confirmed that something about losing first responder is passing NO into that method. What could be causing this, and how can I fix it?
You could break on the method setDocumentEdited: of NSWindow to see which operation updates the change status.
In addition updateChangeCount: of NSDocument might be a place to take a look at.
NSUndoManager also posts several Notifications which can give additional hints what to look at.
The answer is actually pretty silly considering how long this stumped me. I was working on some objects on load, and I accidentally set [[self undoManager] disableUndoRegistration] at both the points where I should disable and enable. It was a little more than that, though. A related element in Interface Builder needed to be checked Prepares Content. When I had done both those things, the problem vanished.