Given that,
1) You have your Data Stack set up
2) You have a model set up, and generated your model object which derives from NSManagedObject. Make sure your properties are @dynamic so that it uses the superclass’s synthesis (via NSManagedObject).
Remember, if you do not use @dynamic, and instead use @synthesize, it means you will be writing the getter/setter method yourself and if you do not write it correctly, the data you save using Core Data will not be there when you restart the app.
for xCode 7 and after, category file is generated
If you are using xCode 7 or after, a category file is generated along with the entity file like so:
- Person+CoreDataProperties.h
- Person+CoreDataProperties.m
- Person.h
- Person.m
The reason for this is because whenever new entity files are generated by doing:
- click on .xcdatamodeld file
- then Editor >> Create NSManagedObject subclass
you won’t have your Entity files overwritten. All your properties and methods will still be there. Instead, xCode will over-ride the Category file(s) instead.
Hence put all your code in Person, and leave the Category file alone.
Implementing the Entity files
Person.h
1 2 3 4 5 6 7 8 |
@interface Person : NSManagedObject { } @property(nonatomic, copy) NSString * firstName; @property(nonatomic, copy) NSString * lastName; @end |
Person.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#import "Person.h" @implementation Person //get/set defined in super class of NSManagedObject, thus we use dynamic //Core Data creates the set and get for us which involved with storing/retrieving data from persistent store @dynamic lastName; @dynamic firstName; -(instancetype)init { if(self=[super init]) { NSLog(@"Person.m - init Person"); self.firstName = @"NA"; self.lastName = @"NA"; return self; } return nil; } @end |
Adding data
In your CoreDataStack.h, we’ll make 2 methods.
- create a new person
- display on all the people who’s in the database into our console.
1 2 |
-(BOOL)makeNewPerson; -(void)reportOnAllPeopleToLog; |
Here are the few important issues when Adding a Person using core data:
1) use insertNewObjectForEntityForName method for Core Data to return you a managed object so you can initialize it with data.
2) Make sure you save context on it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
-(BOOL)makeNewPerson{ NSLog(@"ViewController.m - clicked add person"); //add the entry here CoreDataStack * coreDataStack = [CoreDataStack defaultStack]; //insert new entry into core data environment Person * aPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:coreDataStack.managedObjectContext]; aPerson.firstName = @"testing....."; NSTimeInterval today = [[NSDate date] timeIntervalSince1970]; aPerson.lastName = [NSString stringWithFormat:@"%f", today]; [coreDataStack saveContext]; return aPerson; } |
Here are the few important issues when fetching using core data:
executeFetchRequest gets what we need according to a request. It returns an array and you can iterative through it and display it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
-(void)reportOnAllPeopleToLog { //Get all the projects in the data store NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:[self managedObjectContext]]; request.entity = entity; NSArray *listOfPeople = [[self managedObjectContext] executeFetchRequest:request error:nil]; //List out contents of each project if([listOfPeople count] == 0) NSLog(@"There are no people in the data store yet"); else { NSLog(@"HERE ARE THE People IN THE DATA STORE"); [listOfPeople enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"%lu ----------------", idx); NSLog(@"firstName = %@", [obj firstName]); NSLog(@"lastName = %@", [obj lastName]); }]; } } |
ViewController button and responder
In your UIViewController, add a button and a responder method for both Adding a Person and Logging all the people to the console
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //Specify the type of the button first. No need to use alloc-init for UIButton like other view objects. UIButton * addPersonBtn = [UIButton buttonWithType:UIButtonTypeCustom]; addPersonBtn.frame = CGRectMake(20, 20, 100, 40); [addPersonBtn setBackgroundColor:[UIColor orangeColor]]; [addPersonBtn addTarget:self action:@selector(AddPerson) forControlEvents:UIControlEventTouchUpInside]; addPersonBtn.titleLabel.font = [UIFont fontWithName:@"Arial" size:15]; [addPersonBtn setTitle:@"Add Person" forState:UIControlStateNormal]; [addPersonBtn setTitleColor:[UIColor blackColor] forState:normal]; [addPersonBtn setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter]; [self.view addSubview:addPersonBtn]; } |
Now let’s add a display button. Give it a responder method name displayAll.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
-(void)viewDidLoad { .... .... ... UIButton * displayAllBtn = [UIButton buttonWithType:UIButtonTypeCustom]; // Give UIButtonTypeRoundedRect to get default Interface builder style button. displayAllBtn.frame = CGRectMake(20, 120, 100, 40); [displayAllBtn setBackgroundColor:[UIColor orangeColor]]; // Since the button type is custom, give an image to make it visible. //[myBtn setBackgroundImage:[UIImage imageNamed:@"image.png"] forState:normal]; [displayAllBtn addTarget:self action:@selector(displayAll) forControlEvents:UIControlEventTouchUpInside]; // These are some optional methods you may want to use. displayAllBtn.titleLabel.font = [UIFont fontWithName:@"Arial" size:15]; [displayAllBtn setTitle:@"Display All" forState:UIControlStateNormal]; [displayAllBtn setTitleColor:[UIColor blackColor] forState:normal]; [displayAllBtn setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter]; [self.view addSubview:displayAllBtn]; } |
Implement the button responders:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
-(void)AddPerson { NSLog(@"ViewController.m - clicked add person"); CoreDataStack * coreDataStack = [CoreDataStack defaultStack]; if(![coreDataStack makeNewPerson]) { NSLog(@"uh oh, person not made :("); } } -(void)displayAll { CoreDataStack * coreDataStack = [CoreDataStack defaultStack]; [coreDataStack reportOnAllPeopleToLog]; } |
Now, go ahead and run the project using xcode. Press the Add Person button to add Person objects into the database, and see the results through your console.
Then press the display button to show all the Person objects that’s been saved into the database. Restart the app using your xcode project, press the display button again, and look at the log console to see the objects you’ve saved from before.