Save ManagedObjectContext in Document based App? - cocoa

I have problems saving my MOC in a PersistentDocument.
I insert a new MO in my MOC and do a save (for e.g.)
NSManagedObject *person=[[NSManagedObject alloc] initWithEntity:[NSEntityDescription entityForName:#"Person" inManagedObjectContext:self.managedObjectContext] insertIntoManagedObjectContext:self.managedObjectContext];
if(person)
{
[person setValue:#"test" forKey:#"name"];
NSError *error;
[self.managedObjectContext save:&error];
}
I must save the MO at this point because I need a NOT temporary objectID of it for my background thread to do some calculation on the entity.
But when I save the MOC in this way, I get a requester
The document “Untitled.binary” could not be saved. The file has been changed by another application.
Click Save Anyway to keep your changes and save the changes made by the other application as a version, or click Revert to keep the changes from the other application and save your changes as a version.
the next time the Document is trying to save its content. I can not save the document instead, because it is possible that it is still an untitled document and a call of [document save] would open the save requester which ist not very comfortable for the user.
Is there any solution?
Thanks
Claus

Instead of trying to save you MOC, try
[self.managedObjectContext processPendingChanges];
I had the same issue on an App I'm working on where changes just made would not be there to reference. I tried saving the MOC and keep getting the same message. Calling the processPendingChanges worked for me.

Related

how to show a progress bar on file's icon

You know there is a mini progress bar on the file's icon when we copy a file or download file with safari and chrome.
I am wondering how to let it shown in Finder window when I'm copying or download files with my own code.
Could somebody help me?
Thanks a lot.
I got the way by query file/directory attributes myself. It's quit simple.
Get attributes of the file you want to show a progress bar on it's icon
NSDictionary *fileAttr = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
Get extend attributes
NSDictionary *extendAttr = [fileAttr objectForKey:#"NSFileExtendedAttributes"];
Create a Mutable copy of extendAttr and change some value in it
NSMutableDictionary *mutableExtendAttr = [NSMutableDictionary dictionaryWithDictionary:extendAttr];
// create data of progress value
NSData *progressData = [#"0.1" dataUsingEncoding:NSASCIIStringEncoding];
// change it
[mutableExtendAttr setObject:progressData forKey:#"com.apple.progress.fractionCompleted"];
Create a mutable copy of fileAttr
NSMutableDictionary *mutableFileAttr = [NSMutableDictionary dictionaryWithDictionary:fileAttr];
// change extend attr
[mutableFileAttr setObject:[NSDictionary dictionaryWithDictionary:mutableExtendAttr] forKey:extendAttrKey];
// change file/dir create date to the special one
// if not , progress bar will not show
[mutableFileAttr setObject:[NSDate dateWithString:#"1984-01-24 08:00:00 +0000"] forKey:NSFileCreationDate];
// set attribute to file
[[NSFileManager defaultManager] setAttributes:mutableFileAttr ofItemAtPath:filePath error:&error];
Now you'll find it the progress bar showed up.
One starting point would be to use a NSProgressIndicator, then [progressIndicator setIndeterminate:NO];. Your updates/background operation should then not block the main thread. NSProgressIndicator is a bit different for an AppKit widget -- it permits some updates from secondary threads. Of course, updates to the 'current progress' may also be enqueued upon the main thread's run loop.

Saving data iphone

In my app people can read newsmessages and add a reaction etcetra. The articels are loaded from JSON/XML into a UITableview.
I want to make a new UITableviewController that's called 'favorites' the idea is to put under each article an button to save the message into their 'favorites' in the app.
Does anyone know how to do that? I just need some tips! Do i need to save data in a .plist or do i need to use userdefaults?
Thanks
You can definitely do it either way.
For me, plist saving/loading is at most times easier, but that's just a matter of taste :
NSMutableArray* favorites = [[NSMutableArray alloc] initWithContentsOfFile:filename];

Undo manager not up to date with NSPersistentDocument

I have some calculated values in the core data database that I need to update just before saving. Basically I'm numbering some entities in order to ease up the navigation between them.
Currently I'm observing NSManagedObjectContextWillSaveNotification and trying to do this numbering there. It would seem that the changes that I make are saved but undo manager still seems to have some modifications. This makes the document look like it has changes (mark on the close button) even though managed object context says that it doesn't have (hasChanges). If I undo once, the document looks like it has no changes but in turn, the managed object context does.
Does the undo manager somehow reset itself in the wrong place or am I doing something wrong?
Update
The somewhat obfuscated code in which I'm doing this renumbering looks like this:
- (void)managedObjectContextWillSave:(NSNotification *)notification
{
// Force the content view controller to save any pending changes.
[_contentViewController saveChanges];
NSArray *itemSortDesc = [self sortDescriptorsForSomeItem];
NSArray *items = [SomeItem findAllObjectsInContext:self.managedObjectContext
andSortBy:itemSortDesc];
NSUInteger i = 0;
for (SomeItem *i in items)
{
i.uid = [NSNumber numberWithUnsignedInteger:i++];
}
}
The _contentViewController contains a text field that will be parsed in to multiple instances of SomeItem.
I'm guessing that your numbering affects the undo stack.
I would probably try to handle this in NSManagedObject willSave instead of using NSManagedObjectContextWillSaveNotification but I suspect that won't solve your problem.
You could try this:
[[self.managedObjectContext undoManager] disableUndoRegistration];
// do the renumbering
[self.managedObjectContext processPendingChanges];
[[self.managedObjectContext undoManager] enableUndoRegistration];
I use this to avoid dirtying a brand new document during initialization. I'm not certain it will work correctly for saving, but it might be worth trying.

Check whether save successfully happened in Cocoa Document Based application

I have a Cocoa document based picture editing application. As usual, my application has both File -> Save menu and File -> Save As menu.
File -> Save menu is linked to saveDocument: in NSDocument subclass
File -> Save As menu is linked to saveDocumentAs: in NSDocument subclass
In both cases, on a successful save, I want to present a NSAlert sheet to user saying that the save was successful and this sheet also presents the user with an option to upload the document to Facebook etc.
How do I know, that the document got saved succesfully?
I understand that in case of File -> Save As I can create a new action method mySaveDocument: and invoke
saveDocumentWithDelegate:didSaveSelector:contextInfo:
from mySaveDocument: but what should I do for File -> Save As ?
In your NSDocument subclass, override:
- (BOOL)saveToURL:(NSURL *)absoluteURL
ofType:(NSString *)typeName
forSaveOperation:(NSSaveOperationType)saveOperation
error:(NSError **)outError
{
BOOL success = [super saveToURL:absoluteURL
ofType:typeName
forSaveOperation:saveOperation
error:outError];
if (success) {
…
}
return success;
}
This method is called whenever a document is saved.
For more information on what happens when a document is saved, read the Message Flow in the Document Architecture page of the Document-Based Applications Overview document.

How do I load PersistentDocuments into the same window

I want to open NSPersistentDocuments and load them into the same window one at a time. I'm almost there but missing some steps. Hopefully someone can help me.
I have a few saved documents on the hard drive. On launch my app opens to an untitled NSPersistentDocument and creates a separate NSWindowController. When I press the button to load file 1 off the hard drive the data appears in the fields but two things are wrong that I can see:
1) changing the data doesn't make the document dirty
2) choosing save updates the persistentstore (I know this because when I open the file again I see the changes) but I get an error: +entityForName: could not locate an NSManagedObjectModel for entity name 'Book'
Here's my code which is in the WindowController that was launched initially with the untitled document. This code isn't perfect. For example, I know I should processPendingChanges and save the current doc before I load the new one. This is test code to try to get over this hurdle.
- (IBAction)newBookTwo:(id)sender {
NSDocumentController *dc = [NSDocumentController sharedDocumentController];
NSURL *url = [NSURL fileURLWithPath:[#"~/Desktop/File 2.binary" stringByExpandingTildeInPath]];
NSError *error;
MainWindowDocument *thisDoc = [dc openDocumentWithContentsOfURL:url display:NO error:&error];
[self setDocument:thisDoc];
[self setManagedObjectContext:[thisDoc managedObjectContext]];
}
Thanks!
Assuming you have an entity called "Book" or "book" then the second problem is most likely a typo swapping case. Depending on the entity graph that may be triggering your first problem as well.
Put a break point in there and see if your model is nil.

Resources