Core Data
-Version & Migration
Michael Pan
13年8月15⽇日星期四
Migration
• Automatic (Lightweight) Migration
• Manual Migration
13年8月15⽇日星期四
Lightweight migration can do
• Adding or removing an entity, attribute or relationship
• Make an attribute non-optional with a default value
• Making a non-optional attribute optional
• Renaming an entity or attribute using a renaming identifier
13年8月15⽇日星期四
Create master-detail application
13年8月15⽇日星期四
Check Core Data
13年8月15⽇日星期四
Run it
13年8月15⽇日星期四
Select core data model
13年8月15⽇日星期四
Add ModelVersion
13年8月15⽇日星期四
Version name
13年8月15⽇日星期四
ModifyVersion 2
Entity : Event => Record
13年8月15⽇日星期四
Change the version
13年8月15⽇日星期四
Run - Crash
Unresolved error Error Domain=NSCocoaErrorDomain Code=134100 "The operation couldn’t be completed. (Cocoa error
134100.)" UserInfo=0x834a9f0 {metadata={
NSPersistenceFrameworkVersion = 419;
NSStoreModelVersionHashes = {
Event = <5431c046 d30e7f32 c2cc8099 58add1e7 579ad104 a3aa8fc4 846e97d7 af01cc79>;
};
NSStoreModelVersionHashesVersion = 3;
NSStoreModelVersionIdentifiers = (
""
);
NSStoreType = SQLite;
NSStoreUUID = "E8AAA7FE-4F73-4D13-B7F2-451C0F487E21";
"_NSAutoVacuumLevel" = 2;
}, reason=The model used to open the store is incompatible with the one used to create the store}, {
metadata = {
NSPersistenceFrameworkVersion = 419;
NSStoreModelVersionHashes = {
Event = <5431c046 d30e7f32 c2cc8099 58add1e7 579ad104 a3aa8fc4 846e97d7 af01cc79>;
};
NSStoreModelVersionHashesVersion = 3;
NSStoreModelVersionIdentifiers = (
""
);
NSStoreType = SQLite;
NSStoreUUID = "E8AAA7FE-4F73-4D13-B7F2-451C0F487E21";
"_NSAutoVacuumLevel" = 2;
};
reason = "The model used to open the store is incompatible with the one used to create the store";
}
13年8月15⽇日星期四
Enable auto migration
• AppDelegate.m
• - (NSPersistentStoreCoordinator *)persistentStoreCoordinator
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setValue:@YES forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setValue:@YES forKey:NSInferMappingModelAutomaticallyOption];
if (![_persistentStoreCoordinator
addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL
options:options error:&error]) {
// ignore...
}
13年8月15⽇日星期四
Crash again
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason:
'executeFetchRequest:error: A fetch request must
have an entity.'
13年8月15⽇日星期四
Change Entity name
• MasterViewController.m
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Record"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// ignore ...
}
13年8月15⽇日星期四
Run - ok
13年8月15⽇日星期四
Delete all data first
• remove original codes
• MasterViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
! // Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
// UIBarButtonItem *addButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self
action:@selector(insertNewObject:)];
// self.navigationItem.rightBarButtonItem = addButton;
}
13年8月15⽇日星期四
Change display
13年8月15⽇日星期四
Model v3
V3 V2
13年8月15⽇日星期四
NewRecordViewController
13年8月15⽇日星期四
Add NewViewController
@interface NewRecordViewController : UIViewController
@property (weak, nonatomic) IBOutlet UITextField *commentField;
@property (weak, nonatomic) IBOutlet UITextView *tagsView;
@property (strong) NSManagedObjectContext * context;
@end
13年8月15⽇日星期四
- (IBAction)addNewRecord:(id)sender {
NSManagedObject * newRecord = [NSEntityDescription
insertNewObjectForEntityForName:@"Record" inManagedObjectContext:self.context];
self.recordComment = self.commentField.text;
[newRecord setValue:self.recordComment forKey:@"comment"];
[newRecord setValue:self.recordTags forKey:@"tags"];
NSError * error;
if (![self.context save:&error]) {
if (error) {
NSLog(@"Fail to create new record");
}
}else{
[self.navigationController popViewControllerAnimated:YES];
}
}
Add new record
13年8月15⽇日星期四
Add tag
13年8月15⽇日星期四
TagViewController.h
@protocol TagViewControllerDelegate;
@interface TagViewController : UITableViewController
@property (strong) NSManagedObjectContext * context;
@property (weak) id<TagViewControllerDelegate> delegate;
@end
@protocol TagViewControllerDelegate <NSObject>
-(void) tagView:(TagViewController *) tagView insertNewTag:(NSManagedObject *) tag;
@end
13年8月15⽇日星期四
TagViewController.m
-(void) fetchAllTags{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Tag"
inManagedObjectContext:self.context];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name"
ascending:NO];
NSArray *sortDescriptors = @[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSError * error;
self.tags = [[self.context executeFetchRequest:fetchRequest error:&error]
mutableCopy];
if (error) {
NSLog(@"Can not fetch tags");
}
}
13年8月15⽇日星期四
Add new tag
-(void) insertNewTag:(NSString *) tagName{
NSManagedObject * newTag = [NSEntityDescription
insertNewObjectForEntityForName:@"Tag" inManagedObjectContext:self.context];
[newTag setValue:tagName forKey:@"name"];
NSError * error;
if(![self.context save:&error]){
if (error) {
NSLog(@"Fail to create new tag");
}
}else{
[self.tags addObject:newTag];
[self.tableView reloadData];
}
}
13年8月15⽇日星期四
Send tags to NewRecordViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath
{
if ([self.delegate respondsToSelector:@selector(tagView:insertNewTag:)]) {
[self.delegate tagView:self insertNewTag:self.tags[indexPath.row]];
}
}
13年8月15⽇日星期四
Receive tags in NewRecordViewController
-(void) tagView:(TagViewController *)tagView insertNewTag:(NSManagedObject *)tag{
[self.recordTags addObject:tag];
NSSortDescriptor * sortDescriptor = [NSSortDescriptor
sortDescriptorWithKey:@"name" ascending:YES];
NSSet * nameSet = self.recordTags ;
NSArray * sortedArray = [nameSet
sortedArrayUsingDescriptors:@[sortDescriptor]];
self.tagsView.text = [NSString stringWithFormat:@"%@",[[sortedArray
valueForKey:@"name" ] componentsJoinedByString:@","]];
[self.navigationController popViewControllerAnimated:YES];
}
13年8月15⽇日星期四
Demo - BookingApp
13年8月15⽇日星期四
SQLite debug message
13年8月15⽇日星期四
Delete some version
• Remove .xcdatamodeld (Remove Reference Only)
• Open project in the finder
• find out .xcdatamodeld
• Right-click -> Show Package Contents
• Delete what you want to delete
13年8月15⽇日星期四
Question
13年8月15⽇日星期四

Core data lightweight_migration

  • 1.
    Core Data -Version &Migration Michael Pan 13年8月15⽇日星期四
  • 2.
    Migration • Automatic (Lightweight)Migration • Manual Migration 13年8月15⽇日星期四
  • 3.
    Lightweight migration cando • Adding or removing an entity, attribute or relationship • Make an attribute non-optional with a default value • Making a non-optional attribute optional • Renaming an entity or attribute using a renaming identifier 13年8月15⽇日星期四
  • 4.
  • 5.
  • 6.
  • 7.
    Select core datamodel 13年8月15⽇日星期四
  • 8.
  • 9.
  • 10.
    ModifyVersion 2 Entity :Event => Record 13年8月15⽇日星期四
  • 11.
  • 12.
    Run - Crash Unresolvederror Error Domain=NSCocoaErrorDomain Code=134100 "The operation couldn’t be completed. (Cocoa error 134100.)" UserInfo=0x834a9f0 {metadata={ NSPersistenceFrameworkVersion = 419; NSStoreModelVersionHashes = { Event = <5431c046 d30e7f32 c2cc8099 58add1e7 579ad104 a3aa8fc4 846e97d7 af01cc79>; }; NSStoreModelVersionHashesVersion = 3; NSStoreModelVersionIdentifiers = ( "" ); NSStoreType = SQLite; NSStoreUUID = "E8AAA7FE-4F73-4D13-B7F2-451C0F487E21"; "_NSAutoVacuumLevel" = 2; }, reason=The model used to open the store is incompatible with the one used to create the store}, { metadata = { NSPersistenceFrameworkVersion = 419; NSStoreModelVersionHashes = { Event = <5431c046 d30e7f32 c2cc8099 58add1e7 579ad104 a3aa8fc4 846e97d7 af01cc79>; }; NSStoreModelVersionHashesVersion = 3; NSStoreModelVersionIdentifiers = ( "" ); NSStoreType = SQLite; NSStoreUUID = "E8AAA7FE-4F73-4D13-B7F2-451C0F487E21"; "_NSAutoVacuumLevel" = 2; }; reason = "The model used to open the store is incompatible with the one used to create the store"; } 13年8月15⽇日星期四
  • 13.
    Enable auto migration •AppDelegate.m • - (NSPersistentStoreCoordinator *)persistentStoreCoordinator NSMutableDictionary *options = [NSMutableDictionary dictionary]; [options setValue:@YES forKey:NSMigratePersistentStoresAutomaticallyOption]; [options setValue:@YES forKey:NSInferMappingModelAutomaticallyOption]; if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) { // ignore... } 13年8月15⽇日星期四
  • 14.
    Crash again Terminating appdue to uncaught exception 'NSInvalidArgumentException', reason: 'executeFetchRequest:error: A fetch request must have an entity.' 13年8月15⽇日星期四
  • 15.
    Change Entity name •MasterViewController.m - (NSFetchedResultsController *)fetchedResultsController { if (_fetchedResultsController != nil) { return _fetchedResultsController; } NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; // Edit the entity name as appropriate. NSEntityDescription *entity = [NSEntityDescription entityForName:@"Record" inManagedObjectContext:self.managedObjectContext]; [fetchRequest setEntity:entity]; // ignore ... } 13年8月15⽇日星期四
  • 16.
  • 17.
    Delete all datafirst • remove original codes • MasterViewController.m - (void)viewDidLoad { [super viewDidLoad]; ! // Do any additional setup after loading the view, typically from a nib. self.navigationItem.leftBarButtonItem = self.editButtonItem; // UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)]; // self.navigationItem.rightBarButtonItem = addButton; } 13年8月15⽇日星期四
  • 18.
  • 19.
  • 20.
  • 21.
    Add NewViewController @interface NewRecordViewController: UIViewController @property (weak, nonatomic) IBOutlet UITextField *commentField; @property (weak, nonatomic) IBOutlet UITextView *tagsView; @property (strong) NSManagedObjectContext * context; @end 13年8月15⽇日星期四
  • 22.
    - (IBAction)addNewRecord:(id)sender { NSManagedObject* newRecord = [NSEntityDescription insertNewObjectForEntityForName:@"Record" inManagedObjectContext:self.context]; self.recordComment = self.commentField.text; [newRecord setValue:self.recordComment forKey:@"comment"]; [newRecord setValue:self.recordTags forKey:@"tags"]; NSError * error; if (![self.context save:&error]) { if (error) { NSLog(@"Fail to create new record"); } }else{ [self.navigationController popViewControllerAnimated:YES]; } } Add new record 13年8月15⽇日星期四
  • 23.
  • 24.
    TagViewController.h @protocol TagViewControllerDelegate; @interface TagViewController: UITableViewController @property (strong) NSManagedObjectContext * context; @property (weak) id<TagViewControllerDelegate> delegate; @end @protocol TagViewControllerDelegate <NSObject> -(void) tagView:(TagViewController *) tagView insertNewTag:(NSManagedObject *) tag; @end 13年8月15⽇日星期四
  • 25.
    TagViewController.m -(void) fetchAllTags{ NSFetchRequest *fetchRequest= [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Tag" inManagedObjectContext:self.context]; [fetchRequest setEntity:entity]; [fetchRequest setFetchBatchSize:20]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO]; NSArray *sortDescriptors = @[sortDescriptor]; [fetchRequest setSortDescriptors:sortDescriptors]; NSError * error; self.tags = [[self.context executeFetchRequest:fetchRequest error:&error] mutableCopy]; if (error) { NSLog(@"Can not fetch tags"); } } 13年8月15⽇日星期四
  • 26.
    Add new tag -(void)insertNewTag:(NSString *) tagName{ NSManagedObject * newTag = [NSEntityDescription insertNewObjectForEntityForName:@"Tag" inManagedObjectContext:self.context]; [newTag setValue:tagName forKey:@"name"]; NSError * error; if(![self.context save:&error]){ if (error) { NSLog(@"Fail to create new tag"); } }else{ [self.tags addObject:newTag]; [self.tableView reloadData]; } } 13年8月15⽇日星期四
  • 27.
    Send tags toNewRecordViewController - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath { if ([self.delegate respondsToSelector:@selector(tagView:insertNewTag:)]) { [self.delegate tagView:self insertNewTag:self.tags[indexPath.row]]; } } 13年8月15⽇日星期四
  • 28.
    Receive tags inNewRecordViewController -(void) tagView:(TagViewController *)tagView insertNewTag:(NSManagedObject *)tag{ [self.recordTags addObject:tag]; NSSortDescriptor * sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; NSSet * nameSet = self.recordTags ; NSArray * sortedArray = [nameSet sortedArrayUsingDescriptors:@[sortDescriptor]]; self.tagsView.text = [NSString stringWithFormat:@"%@",[[sortedArray valueForKey:@"name" ] componentsJoinedByString:@","]]; [self.navigationController popViewControllerAnimated:YES]; } 13年8月15⽇日星期四
  • 29.
  • 30.
  • 31.
    Delete some version •Remove .xcdatamodeld (Remove Reference Only) • Open project in the finder • find out .xcdatamodeld • Right-click -> Show Package Contents • Delete what you want to delete 13年8月15⽇日星期四
  • 32.