2

I'm trying to use Core Data in my iPad application.

I have a model like:

Customer.h

#import <CoreData/CoreData.h>
@interface Customer : NSManagedObject
@property (nonatomic,strong) NSString *name;
@end

Customer.m

#import "Customer.h"
@implementation Customer
@synthesize name;
@end

The table view controller shows all the customers in the database. By selecting a customer a details view push segue is started and customer is set:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.

    CustomerDetailViewController *detailViewController = (CustomerDetailViewController*)   [segue destinationViewController];
    detailViewController.customer = [customers objectAtIndex:self.tableView.indexPathForSelectedRow.row];
}

In detail view controller the action save should save the customer if changed:

- (IBAction)save:(id)sender 
{
  AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
  NSManagedObjectContext *moc = [delegate managedObjectContext];
  self.customer.name = self.nameTextField.text;
  NSError *error;
  if (![moc save:&error]) 
  {
    NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
  }
}

Although the name is changed, the changes are not saved: no error arises though (error is nil, log not shown)...

Moreover:

  BOOL customerHasChanges = [self.customer hasChanges];
  BOOL mocHasChanges = [moc hasChanges];

are both false!

However inserting new entities works fine:

Customer *customer = [NSEntityDescription insertNewObjectForEntityForName:@"Customer" inManagedObjectContext:self.managedObjectContext];
[customer setValue:@"Mars Inc." forKey:@"name"];
NSError *error; 
[self.managedObjectContext save:&error];
Cœur
  • 37,241
  • 25
  • 195
  • 267
Lula
  • 43
  • 1
  • 6
  • How are you checking that it saved the customer name? – RyanR Oct 20 '13 at 13:55
  • I suspect that something is wrong with your managed object context. Try to get it via the managed object: `customer.managedObjectContext`. – Mundi Oct 20 '13 at 14:44
  • @RyanR: I meant that although the name is actually changed (self.customer.name = self.nameTextField.text), the entity is not changed (e.g. [customer hasChanges] returns false). – Lula Oct 21 '13 at 08:00
  • @Mundi: I tried to get the managedObjectContext from the entity itself, but changes are not saved anyway. – Lula Oct 21 '13 at 08:01
  • `-hasChanges` will only return true is you haven't called save, but your code shows you are calling save immediately. I'm asking how you know the changed name doesn't persist to the database - are you querying the sqlite, or what? – RyanR Oct 21 '13 at 14:04
  • @RyanR well, those are pieces of code put here and there in the post: I checked the hasChanges before calling save. I know changes are not persisted by checking the database directly. – Lula Oct 21 '13 at 18:13

1 Answers1

4

You have an error in your implementation file. Use @dynamic instead of @synthesize.

Mundi
  • 79,884
  • 17
  • 117
  • 140
  • Thanks a lot man! That solved my issue! Could you please quickly explain me why should I use @dynamic instead of @property? – Lula Oct 21 '13 at 18:10
  • Read all about it in the [official documentation](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html). – Mundi Oct 21 '13 at 18:19
  • Thanks for this. It works for me as well. But still can you please explain why it did not work with @synthesize? – webdev May 04 '14 at 03:09
  • Even when the SO OP is directed to read the official doc, he/she still expects a short StackOverflow answer which will leave a huge vacuum of knowledge after sometime in his/her career life! :-) – Randika Vishman Apr 27 '18 at 07:24