views:

440

answers:

2

Hello guys,

I have an optional binary attribute: image , containing an image for my entities. In the interface, I have NSImageView (Image Well), and a "Remove Image" button. When the image removing button is clicked, I do:

- (IBAction)saveAction:(id)sender {
  NSError *error = nil;
  if (![[self managedObjectContext] save:&error]) {
    [[NSApplication sharedApplication] presentError:error];
  }
  [tableView reloadData];
}

- (IBAction)removeImage:(id)sender {
  [image setImage:nil]; // image is a NSImageView outlet bound to the image attribute.
  [self saveAction:sender];
}

It clears the image from the NSImageView, but the binary data is still retained in the Core Data entity.

How do I reflect the change in the Core Data entity as well?

Thanks!

Edit:

NSImageView is already bound to model's image attribute, and available as outlet too. So I'm just looking for someone to tell me how to reset the attribute by fetching the model (if that's what I need to do).

Would appreciate any code help. :)

+3  A: 
[image setImage:nil];

Is image actually an image view? If so, I must remind you to name your instance variables clearly and accurately.

You need to set the image property of the model object(s), not the view(s). Bind the views through the controllers to the model; then, when you change the model, the views pick up the changes for free.

Peter Hosey
Yes, `image` is an NSImageView outlet. I changed it's name for the context here.You said, "Bind the views through the controllers to the model". Can you refer me to some code I need to employ for that? I'm fairly new to deal with Core Data programmatically. Thanks for your help!
Gurpartap Singh
You normally set up bindings in IB. The only reason to do it programmatically is that you've made one or more custom view classes and don't want to make an IB plug-in for them. For more information, see the Cocoa Bindings Programming Topics: http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/
Peter Hosey
I don't know how binding programmatically or through Interface Builder makes a difference here. I appreciate your help. I would also appreciate if I can get some direct code that'll help me finish this faster.
Gurpartap Singh
It doesn't. The only difference is that binding through IB is usually easier. The result is the same either way.
Peter Hosey
So yeah, how do I reset the model entity's image? (instead of NSImageView, which I believe, I'll also need to, when a new entity hasn't yet been saved; but leave that for now.)
Gurpartap Singh
You only need to set the view's property if you haven't bound its content binding to your model's image property. That's why you should bind it: so you don't have to set the view's property as well as the model's.
Peter Hosey
Anyway, you need to obtain the model object that has the image, then set its image property (the one you defined in the object model) to nil.
Peter Hosey
Dude, that's exactly what I'm doing. You have been discussing what I already know.NSImageView is already bound to model's image, and available as outlet to be reset. So I'm just looking for someone to tell me how to reset the attribute by fetching the model. The only thing that I came to stackoverflow was for some code help. Thank you.
Gurpartap Singh
That wasn't clear from your question. And it *is* what you need to do—this is how (modern) Cocoa works. Once you make the change in the model, all views bound to it will pick up the change for free.
Peter Hosey
Sadly, I don't use Core Data, so I don't know first-hand the best way for your controller to retrieve the model objects. You might try this: http://developer.apple.com/documentation/Cocoa/Conceptual/CoreData/Articles/cdFetching.html
Peter Hosey
A: 

I was under impression that altering an array from a fetch request won't make a difference to the actual data in storage. But I was wrong. I tried and it worked! Thanks Peter, and everyone elsewhere!

Here's what I replaced my image removal function for currently selected entity having a unique attribute:

- (IBAction)removeImage:(id)sender {
  // Fetch the entity in question.
  NSManagedObjectContext *context = [self managedObjectContext];
  NSManagedObjectModel *model = [self managedObjectModel];
  NSEntityDescription *entity = [[model entitiesByName] valueForKey:@"myEntity"];
  NSPredicate *predicate = [NSPredicate predicateWithFormat:
                            @"unique_attr == %@", [unique_attr_outlet stringValue]];
  NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
  [fetch setEntity:entity];
  [fetch setPredicate:predicate];

  // Load it into NSArray object and remove the binary data attribute.
  NSArray *contextArray = [context executeFetchRequest:fetch error:nil];
  if ([contextArray count] > 0)
    [[contextArray objectAtIndex:0] setValue:nil forKey:@"myImage"];

  [fetch release];
}
Gurpartap Singh