Created
March 11, 2014 04:33
-
-
Save keicoder/9479571 to your computer and use it in GitHub Desktop.
objective-c : Core Data Essential (CDCourses)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Core Data Essential (CDCourses) | |
//Course.h | |
#import <CoreData/CoreData.h> | |
@interface Course : NSManagedObject | |
@property (nonatomic, retain) NSString * title; | |
@property (nonatomic, retain) NSString * author; | |
@property (nonatomic, retain) NSDate * releaseDate; | |
@end | |
//Course.m | |
@implementation Course | |
@dynamic title; | |
@dynamic author; | |
@dynamic releaseDate; | |
//Invoked automatically by the Core Data framework when the receiver is first inserted into a managed object context. | |
//typically use this method to initialize special default property values. | |
//awakeFromInsert method is invoked only once in the object's lifetime | |
- (void) awakeFromInsert | |
{ | |
[super awakeFromInsert]; | |
self.releaseDate = [NSDate date]; | |
} | |
@end | |
//AppDelegate.h | |
#import "CoursesTableViewController.h" | |
@interface AppDelegate : UIResponder <UIApplicationDelegate> | |
@property (strong, nonatomic) UIWindow *window; | |
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; | |
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; | |
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; | |
- (void)saveContext; | |
- (NSURL *)applicationDocumentsDirectory; | |
@end | |
//AppDelegate.m | |
@implementation AppDelegate | |
@synthesize managedObjectContext = _managedObjectContext; | |
@synthesize managedObjectModel = _managedObjectModel; | |
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator; | |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions | |
{ | |
// 스토리보드를 사용하므로 스텁 코드는 삭제함. | |
// 루트 뷰로 내비게이션컨트롤러 설정 및 managedObjectContext 참조 | |
UINavigationController *nav = (UINavigationController *)self.window.rootViewController; | |
CoursesTableViewController *ctvc = (CoursesTableViewController *)[[nav viewControllers] objectAtIndex:0]; | |
ctvc.managedObjectContext = self.managedObjectContext; | |
return YES; | |
} | |
- (void)applicationWillTerminate:(UIApplication *)application | |
{ | |
// Saves changes in the application's managed object context before the application terminates. | |
[self saveContext]; | |
} | |
- (void)saveContext | |
{ | |
NSError *error = nil; | |
NSManagedObjectContext *managedObjectContext = self.managedObjectContext; | |
if (managedObjectContext != nil) { | |
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { | |
NSLog(@"Unresolved error %@, %@", error, [error userInfo]); | |
abort(); | |
} | |
} | |
} | |
#pragma mark - Core Data stack | |
// Returns the managed object context for the application. | |
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application. | |
- (NSManagedObjectContext *)managedObjectContext | |
{ | |
if (_managedObjectContext != nil) { | |
return _managedObjectContext; | |
} | |
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; | |
if (coordinator != nil) { | |
_managedObjectContext = [[NSManagedObjectContext alloc] init]; | |
[_managedObjectContext setPersistentStoreCoordinator:coordinator]; | |
} | |
return _managedObjectContext; | |
} | |
// Returns the managed object model for the application. | |
// If the model doesn't already exist, it is created from the application's model. | |
- (NSManagedObjectModel *)managedObjectModel | |
{ | |
if (_managedObjectModel != nil) { | |
return _managedObjectModel; | |
} | |
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CDCourses" withExtension:@"momd"]; | |
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; | |
return _managedObjectModel; | |
} | |
// Returns the persistent store coordinator for the application. | |
// If the coordinator doesn't already exist, it is created and the application's store added to it. | |
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator | |
{ | |
if (_persistentStoreCoordinator != nil) { | |
return _persistentStoreCoordinator; | |
} | |
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CDCourses.sqlite"]; | |
NSError *error = nil; | |
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; | |
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { | |
/* | |
Replace this implementation with code to handle the error appropriately. | |
*/ | |
NSLog(@"Unresolved error %@, %@", error, [error userInfo]); | |
abort(); | |
} | |
return _persistentStoreCoordinator; | |
} | |
#pragma mark - Application's Documents directory | |
// Returns the URL to the application's Documents directory. | |
- (NSURL *)applicationDocumentsDirectory | |
{ | |
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; | |
} | |
@end | |
//AddCourseViewController.h | |
#import "Course.h" | |
@protocol AddCourseViewControllerDelegate; | |
@interface AddCourseViewController : UIViewController | |
@property (weak, nonatomic) IBOutlet UITextField *titleField; | |
@property (weak, nonatomic) IBOutlet UITextField *authorField; | |
@property (weak, nonatomic) IBOutlet UITextField *dateField; | |
@property (nonatomic, weak) id <AddCourseViewControllerDelegate> delegate; | |
@property (nonatomic, strong) Course *currentCourse; | |
- (IBAction)cancel:(id)sender; | |
- (IBAction)save:(id)sender; | |
@end | |
@protocol AddCourseViewControllerDelegate | |
- (void) addCourseViewControllerDidSave; | |
- (void) addCourseViewControllerDidCancel:(Course *)courseToDelete; | |
@end | |
// AddCourseViewController.m | |
@interface AddCourseViewController () | |
@end | |
@implementation AddCourseViewController | |
@synthesize titleField; | |
@synthesize authorField; | |
@synthesize dateField; | |
#pragma mark - 뷰 라이프 사이클 | |
- (void)viewDidLoad | |
{ | |
[super viewDidLoad]; | |
titleField.text = [self.currentCourse title]; | |
authorField.text = [self.currentCourse author]; | |
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; | |
[dateFormat setDateFormat:@"yyyy-MM-dd"]; | |
dateField.text = [dateFormat stringFromDate:[self.currentCourse releaseDate]]; | |
} | |
- (IBAction)cancel:(id)sender { | |
// 모달 뷰 팝 / 오브젝트 제거 | |
[self.delegate addCourseViewControllerDidCancel:[self currentCourse]]; | |
} | |
- (IBAction)save:(id)sender { | |
// 모달 뷰 팝 / 컨텍스트 저장 | |
[self.currentCourse setTitle:titleField.text]; | |
[self.currentCourse setAuthor:authorField.text]; | |
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; | |
[dateFormat setDateFormat:@"yyyy-mm-dd"]; | |
[self.currentCourse setReleaseDate:[dateFormat dateFromString:dateField.text]]; | |
[self.delegate addCourseViewControllerDidSave]; | |
} | |
@end | |
//CoursesTableViewController.h | |
#import "AddCourseViewController.h" | |
// 컨텍스트의 저장/저장 취소/모달 뷰 해제를 위한 델리게이트 | |
@interface CoursesTableViewController : UITableViewController <AddCourseViewControllerDelegate, NSFetchedResultsControllerDelegate> | |
// AppDelegate의 컨텍스트 참조 | |
@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; | |
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController; | |
@end | |
//CoursesTableViewController.m | |
#import "Course.h" | |
#import "DisplayEditViewController.h" | |
@implementation CoursesTableViewController | |
@synthesize fetchedResultsController = _fetchedResultsController; | |
#pragma mark - addCourseViewControllerDelegate 메소드 | |
- (void) addCourseViewControllerDidCancel:(Course *)courseToDelete | |
{ | |
NSManagedObjectContext *context = self.managedObjectContext; | |
[context deleteObject:courseToDelete]; | |
[self dismissViewControllerAnimated:YES completion:nil]; | |
} | |
- (void) addCourseViewControllerDidSave | |
{ | |
NSError *error = nil; | |
NSManagedObjectContext *context = self.managedObjectContext; | |
if (![context save:&error]) { | |
NSLog(@"Error! %@", error); | |
} | |
[self dismissViewControllerAnimated:YES completion:nil]; | |
} | |
#pragma mark - Segue 메소드 | |
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { | |
if ([[segue identifier] isEqualToString:@"addCourse"]) { | |
AddCourseViewController *acvc = (AddCourseViewController *)[segue destinationViewController]; | |
acvc.delegate =self; | |
Course *newCourse = (Course *) [NSEntityDescription insertNewObjectForEntityForName:@"Course" inManagedObjectContext:[self managedObjectContext]]; | |
acvc.currentCourse = newCourse; | |
} | |
if ([[segue identifier] isEqualToString:@"showDetail"]) { | |
DisplayEditViewController *dvc = (DisplayEditViewController *) [segue destinationViewController]; | |
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; | |
Course *selectedCourse = (Course *) [self.fetchedResultsController objectAtIndexPath:indexPath]; | |
dvc.currentCourse = selectedCourse; | |
} | |
} | |
#pragma mark - 뷰 라이프 사이클 | |
- (void)viewDidLoad | |
{ | |
[super viewDidLoad]; | |
// performFetch | |
NSError *error = nil; | |
if (![[self fetchedResultsController] performFetch:&error]) { | |
NSLog(@"Error! %@", error); | |
abort(); | |
} | |
} | |
#pragma mark - fetchedResultsController section (지연된 로딩) | |
-(NSFetchedResultsController *) fetchedResultsController { | |
if (_fetchedResultsController != nil) { | |
return _fetchedResultsController; | |
} | |
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; | |
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Course" | |
inManagedObjectContext:[self managedObjectContext]]; | |
[fetchRequest setEntity:entity]; | |
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"author" | |
ascending:YES]; | |
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; | |
[fetchRequest setSortDescriptors:sortDescriptors]; | |
// fetchedResultsController 엑세서 메소드 | |
_fetchedResultsController = [[NSFetchedResultsController alloc] | |
initWithFetchRequest:fetchRequest | |
managedObjectContext:self.managedObjectContext | |
sectionNameKeyPath:@"author" | |
cacheName:nil]; | |
_fetchedResultsController.delegate = self; | |
return _fetchedResultsController; | |
} | |
#pragma mark - fetchedResultsController 델리게이트 메소드 | |
-(void) controllerWillChangeContent:(NSFetchedResultsController *)controller { | |
[self.tableView beginUpdates]; | |
} | |
-(void) controllerDidChangeContent:(NSFetchedResultsController *)controller { | |
[self.tableView endUpdates]; | |
} | |
-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { | |
UITableView *tableView = self.tableView; | |
switch (type) { | |
case NSFetchedResultsChangeInsert: | |
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] | |
withRowAnimation:UITableViewRowAnimationFade]; | |
break; | |
case NSFetchedResultsChangeDelete: | |
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] | |
withRowAnimation:UITableViewRowAnimationFade]; | |
break; | |
case NSFetchedResultsChangeUpdate: { | |
Course *changedCourse = [self.fetchedResultsController objectAtIndexPath:indexPath]; | |
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; | |
cell.textLabel.text = changedCourse.title; | |
} | |
break; | |
case NSFetchedResultsChangeMove: | |
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] | |
withRowAnimation:UITableViewRowAnimationFade]; | |
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] | |
withRowAnimation:UITableViewRowAnimationFade]; | |
break; | |
} | |
} | |
-(void) controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { | |
switch (type) { | |
case NSFetchedResultsChangeInsert: | |
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] | |
withRowAnimation:UITableViewRowAnimationFade]; | |
break; | |
case NSFetchedResultsChangeDelete: | |
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] | |
withRowAnimation:UITableViewRowAnimationFade]; | |
break; | |
} | |
} | |
#pragma mark - Table view data source | |
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView | |
{ | |
return [[self.fetchedResultsController sections] count]; | |
} | |
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section | |
{ | |
// <NSFetchedResultsSectionInfo> 프로토콜 | |
id <NSFetchedResultsSectionInfo> secInfo = [[self.fetchedResultsController sections] objectAtIndex:section]; | |
return [secInfo numberOfObjects]; | |
} | |
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath | |
{ | |
static NSString *CellIdentifier = @"Cell"; | |
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; | |
// Configure the cell... | |
Course *course = [self.fetchedResultsController objectAtIndexPath:indexPath]; | |
cell.textLabel.text = course.title; | |
return cell; | |
} | |
- (NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section | |
{ | |
return [[[self.fetchedResultsController sections] objectAtIndex:section] name]; | |
} | |
#pragma mark - Table view 에디팅 지원 | |
// Override to support editing the table view. | |
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath | |
{ | |
if (editingStyle == UITableViewCellEditingStyleDelete) { | |
NSManagedObjectContext *context = [self managedObjectContext]; | |
Course *courseToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath]; | |
[context deleteObject:courseToDelete]; | |
NSError *error = nil; | |
if (![context save:&error]) { | |
NSLog(@"Error! %@",error); | |
} | |
} | |
} | |
@end | |
//DisplayEditViewController.h | |
#import "Course.h" | |
@interface DisplayEditViewController : UIViewController | |
@property (nonatomic, strong) Course *currentCourse; | |
@property (weak, nonatomic) IBOutlet UITextField *titleField; | |
@property (weak, nonatomic) IBOutlet UITextField *authorField; | |
@property (weak, nonatomic) IBOutlet UITextField *dateField; | |
@property (weak, nonatomic) IBOutlet UIButton *editButton; | |
@property (weak, nonatomic) IBOutlet UIButton *doneButton; | |
- (IBAction)startEditing:(id)sender; | |
- (IBAction)doneEditing:(id)sender; | |
@end | |
//DisplayEditViewController.m | |
#import "DisplayEditViewController.h" | |
#import "AppDelegate.h" | |
@interface DisplayEditViewController () | |
@end | |
@implementation DisplayEditViewController | |
@synthesize titleField; | |
@synthesize authorField; | |
@synthesize dateField; | |
@synthesize editButton; | |
@synthesize doneButton; | |
- (void)viewDidLoad | |
{ | |
[super viewDidLoad]; | |
titleField.text = [self.currentCourse title]; | |
authorField.text = [self.currentCourse author]; | |
NSDateFormatter *df = [[NSDateFormatter alloc]init]; | |
[df setDateFormat:@"yyyy-MM-dd"]; | |
dateField.text = [df stringFromDate:[self.currentCourse releaseDate]]; | |
} | |
- (IBAction)startEditing:(id)sender { | |
titleField.enabled = YES; | |
authorField.enabled = YES; | |
dateField.enabled = YES; | |
titleField.borderStyle = UITextBorderStyleRoundedRect; | |
authorField.borderStyle = UITextBorderStyleRoundedRect; | |
dateField.borderStyle = UITextBorderStyleRoundedRect; | |
editButton.hidden = YES; | |
doneButton.hidden = NO; | |
} | |
- (IBAction)doneEditing:(id)sender { | |
titleField.enabled = NO; | |
authorField.enabled = NO; | |
dateField.enabled = NO; | |
titleField.borderStyle = UITextBorderStyleNone; | |
authorField.borderStyle = UITextBorderStyleNone; | |
dateField.borderStyle = UITextBorderStyleNone; | |
editButton.hidden = NO; | |
doneButton.hidden = YES; | |
_currentCourse.title = titleField.text; | |
_currentCourse.author = authorField.text; | |
NSDateFormatter *df = [[NSDateFormatter alloc] init]; | |
[df setDateFormat:@"yyyy-MM-dd"]; | |
_currentCourse.releaseDate = [df dateFromString:dateField.text]; | |
// 앱 델리게이트 컨텍스트 저장 | |
AppDelegate *myApp = (AppDelegate *) [[UIApplication sharedApplication] delegate]; | |
[myApp saveContext]; | |
} | |
@end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment