Created
March 13, 2014 04:47
-
-
Save keicoder/9522023 to your computer and use it in GitHub Desktop.
objective-c : Note with Core Data (SwiftNote5)
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
//Note with Core Data (SwiftNote5) | |
//1. save, delete, edit note with coredata (AddNoteView, TableView) | |
//AppDelegate.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 | |
#import "NoteListTableViewController.h" | |
@implementation AppDelegate | |
@synthesize managedObjectContext = _managedObjectContext; | |
@synthesize managedObjectModel = _managedObjectModel; | |
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator; | |
#pragma mark - DidFinishLaunchingWithOptions | |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions | |
{ | |
// Override point for customization after application launch. | |
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController; | |
NoteListTableViewController *controller = (NoteListTableViewController *)navigationController.topViewController; | |
controller.managedObjectContext = self.managedObjectContext; | |
return YES; | |
} | |
#pragma mark - 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 - CoreData 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:@"SwiftNote5" 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:@"SwiftNote5.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]; | |
} | |
#pragma mark - application 상태 | |
- (void)applicationWillTerminate:(UIApplication *)application | |
{ | |
[self saveContext]; | |
} | |
@end | |
//CoreViewController.h | |
#import <QuartzCore/QuartzCore.h> // 테두리가 둥근 UITextView 만들기 | |
@interface CoreViewController : UIViewController | |
#pragma mark - 테두리가 둥근 UITextView 만들기 | |
- (void)roundCorneredTextView:(UITextView *)textView; | |
@end | |
//CoreViewController.m | |
@implementation CoreViewController | |
#pragma mark - 테두리가 둥근 UITextView 만들기 : QuartzCore 프레임워크 | |
- (void)roundCorneredTextView:(UITextView *)textView | |
{ | |
// 테두리가 둥근 UITextView 만들기 | |
textView.layer.cornerRadius = 10; | |
textView.clipsToBounds = YES; | |
} | |
@end | |
//AddNoteViewController.h | |
#import "CoreViewController.h" | |
#import "Note.h" | |
@protocol AddNoteViewControllerDelegate; | |
@interface AddNoteViewController : CoreViewController <UITextViewDelegate, UITextFieldDelegate> | |
@property (strong, nonatomic) IBOutlet UITextField *noteTitleTextField; | |
@property (strong, nonatomic) IBOutlet UITextView *noteTextView; | |
//AddNoteViewControllerDelegate | |
@property (nonatomic, weak) id <AddNoteViewControllerDelegate> delegate; | |
@property (nonatomic, strong) Note *currentNote; | |
@end | |
#pragma mark - AddNoteViewControllerDelegate : AddView의 상태변경을 테이블 뷰에 알려주고 저장/취소/뷰 해제 등을 하기 위한 델리게이트 메소드 | |
@protocol AddNoteViewControllerDelegate | |
-(void)addNoteViewControllerDidSave; | |
-(void)addNoteViewControllerDidCancel:(Note *)noteToDelete; | |
@end | |
//AddNoteViewController.m | |
#import "AddNoteViewController.h" | |
@interface AddNoteViewController () <UITextViewDelegate, UITextFieldDelegate> | |
@property (strong, nonatomic) IBOutlet UIBarButtonItem *saveButton; | |
@end | |
@implementation AddNoteViewController | |
@synthesize noteTitleTextField; | |
@synthesize noteTextView; | |
#pragma mark - View Life Cycle | |
- (void)viewDidLoad | |
{ | |
[super viewDidLoad]; | |
[super roundCorneredTextView:self.noteTextView]; // CoreViewController의 roundCorneredTextView 메소드로 테두리가 둥근 UITextView 만들기 | |
} | |
#pragma mark - Memory Warning | |
- (void)didReceiveMemoryWarning | |
{ | |
[super didReceiveMemoryWarning]; | |
} | |
#pragma mark - Button Action Method: save나 cancel 버튼 click시 delegate method call | |
- (IBAction)cancelButtonPressed:(UIBarButtonItem *)sender { | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
//remove the object | |
[self.delegate addNoteViewControllerDidCancel:[self currentNote]]; | |
} | |
- (IBAction)saveButtonPressed:(UIBarButtonItem *)sender { | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
//save the context | |
[self.currentNote setNoteTitle:noteTitleTextField.text]; | |
[self.currentNote setNoteBody:noteTextView.text]; | |
[self.delegate addNoteViewControllerDidSave]; | |
} | |
@end | |
//NoteListTableViewController.h | |
#import "AddNoteViewController.h" | |
@interface NoteListTableViewController : UITableViewController <AddNoteViewControllerDelegate, NSFetchedResultsControllerDelegate> | |
@property (strong, nonatomic) NSManagedObjectContext *managedObjectContext; | |
@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController; //manage the results returned from a Core Data fetch request to provide data for a UITableView object | |
@end | |
// NoteListTableViewController.m | |
#import "Note.h" | |
@implementation NoteListTableViewController | |
@synthesize fetchedResultsController = _fetchedResultsController; | |
#pragma mark - AddNoteViewController Delegate | |
-(void)addNoteViewControllerDidCancel:(Note *)noteToDelete { | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
NSManagedObjectContext *context = self.managedObjectContext; | |
[context deleteObject:noteToDelete]; | |
NSLog(@"Delete note object!"); | |
[self dismissViewControllerAnimated:YES completion:^{ | |
NSLog (@"Dismiss AddNoteView Complete!"); | |
}]; | |
} | |
-(void) addNoteViewControllerDidSave { | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
NSError *error = nil; | |
NSManagedObjectContext *context = self.managedObjectContext; | |
if (![context save:&error]) { | |
NSLog(@"Error! %@", error); | |
} | |
NSLog(@"Save note object!"); | |
[self dismissViewControllerAnimated:YES completion:^{ | |
NSLog(@"Dismiss AddNoteView Complete!"); | |
}]; | |
} | |
#pragma mark - PrepareForSegue | |
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { | |
if ([[segue identifier] isEqualToString:@"AddNote"]) { | |
UINavigationController *nav = [segue destinationViewController]; | |
AddNoteViewController *anvc = (AddNoteViewController *)[nav topViewController]; | |
anvc.delegate =self; | |
Note *newNote = (Note *) [NSEntityDescription | |
insertNewObjectForEntityForName:@"Note" | |
inManagedObjectContext:[self managedObjectContext]]; | |
anvc.currentNote = newNote; | |
} | |
} | |
#pragma mark - View Life Cycle | |
- (void)viewDidLoad | |
{ | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
[super viewDidLoad]; | |
//performFetch | |
NSError *error = nil; | |
if (![[self fetchedResultsController] performFetch:&error]) { | |
NSLog(@"Error! %@",error); | |
abort(); | |
} | |
NSLog (@"performFetch!"); | |
} | |
#pragma mark - TableView DataSource | |
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView | |
{ | |
return [[self.fetchedResultsController sections]count]; | |
} | |
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section | |
{ | |
id <NSFetchedResultsSectionInfo> secInfo = [[self.fetchedResultsController sections] objectAtIndex:section]; | |
return [secInfo numberOfObjects]; | |
} | |
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath | |
{ | |
static NSString *CellIdentifier = @"Cell"; | |
// much simpler way | |
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; | |
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; | |
if (cell == nil) { | |
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; | |
} | |
// Configure the cell... | |
Note *note = [self.fetchedResultsController objectAtIndexPath:indexPath]; | |
cell.textLabel.text = note.noteTitle; | |
return cell; | |
} | |
#pragma mark - TableView 헤더 | |
-(NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { | |
return [[[self.fetchedResultsController sections]objectAtIndex:section]name]; | |
} | |
#pragma mark - TableView 행 높이 | |
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath | |
{ | |
return 50; | |
} | |
#pragma mark - TableView 편집 | |
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath | |
{ | |
if (editingStyle == UITableViewCellEditingStyleDelete) { | |
NSManagedObjectContext *context = [self managedObjectContext]; | |
Note *noteToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath]; | |
[context deleteObject:noteToDelete]; | |
// Save 컨텍스트 | |
NSError *error = nil; | |
if (![context save:&error]) { | |
NSLog(@"Unresolved error %@, %@", error, [error userInfo]); | |
} | |
} | |
} | |
#pragma mark - NSFetchedResultsController | |
- (NSFetchedResultsController *)fetchedResultsController | |
{ | |
if (_fetchedResultsController != nil) { | |
return _fetchedResultsController; | |
} | |
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; | |
// Edit the entity name as appropriate. | |
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Note" inManagedObjectContext:self.managedObjectContext]; | |
[fetchRequest setEntity:entity]; | |
// Set the batch size to a suitable number. | |
[fetchRequest setFetchBatchSize:20]; | |
// Edit the sort key as appropriate. | |
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"noteTitle" ascending:YES]; | |
NSArray *sortDescriptors = @[sortDescriptor]; | |
[fetchRequest setSortDescriptors:sortDescriptors]; | |
// Edit the section name key path and cache name if appropriate. | |
// nil for section name key path means "no sections". | |
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"noteTitle" cacheName:nil]; | |
_fetchedResultsController.delegate = self; | |
return _fetchedResultsController; | |
} | |
#pragma mark - NSFetchedResultsController Delegate Method | |
// 섹션 수정사항 반영 | |
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller | |
{ | |
[self.tableView beginUpdates]; | |
} | |
- (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; | |
} | |
} | |
// 컨텐츠 수정사항 반영 | |
- (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:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; | |
break; | |
case NSFetchedResultsChangeDelete: | |
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; | |
break; | |
case NSFetchedResultsChangeUpdate: { | |
Note *changedNote = [self.fetchedResultsController objectAtIndexPath:indexPath]; | |
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; | |
cell.textLabel.text = changedNote.noteTitle; | |
} | |
break; | |
case NSFetchedResultsChangeMove: | |
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; | |
[tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; | |
break; | |
} | |
} | |
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller | |
{ | |
[self.tableView endUpdates]; | |
// [self.tableView reloadData]; | |
} | |
#pragma mark - Memory Warning | |
- (void)didReceiveMemoryWarning | |
{ | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
[super didReceiveMemoryWarning]; | |
} | |
@end | |
//2. save, delete, edit note with coredata (DisplayEditView, TableView) | |
//NoteListTableViewController.m | |
#import "DisplayEditViewController.h" | |
@implementation NoteListTableViewController | |
#pragma mark - PrepareForSegue | |
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { | |
//... | |
if ([[segue identifier] isEqualToString:@"EditNote"]) { | |
DisplayEditViewController *devc = (DisplayEditViewController *)[segue destinationViewController]; | |
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; | |
Note *selectedNote = (Note *)[self.fetchedResultsController objectAtIndexPath:indexPath]; | |
devc.currentNote = selectedNote; | |
} | |
} | |
//DisplayEditViewController.h | |
#import "CoreViewController.h" | |
#import "Note.h" | |
@interface DisplayEditViewController : CoreViewController | |
@property (nonatomic, strong) Note *currentNote; | |
@end | |
//DisplayEditViewController.m | |
#import "AppDelegate.h" //saveContext 메소드 호출 | |
@interface DisplayEditViewController () | |
@property (strong, nonatomic) IBOutlet UITextField *noteTitleTextField; | |
@property (strong, nonatomic) IBOutlet UITextView *noteTextView; | |
@end | |
@implementation DisplayEditViewController | |
#pragma mark - View Life Cycle | |
- (void)viewDidLoad | |
{ | |
if (debug==1) {NSLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd));} | |
[super viewDidLoad]; | |
self.noteTitleTextField.text = [self.currentNote noteTitle]; | |
self.noteTextView.text = [self.currentNote noteBody]; | |
// CoreViewController의 roundCorneredTextView 메소드로 테두리가 둥근 UITextView 만들기 | |
[super roundCorneredTextView:self.noteTextView]; | |
} | |
#pragma mark - Bar Button Action Method: 컨텍스트 저장, 뷰 pop | |
- (IBAction)saveButtonPressed:(UIBarButtonItem *)sender | |
{ | |
_currentNote.noteTitle = self.noteTitleTextField.text; | |
_currentNote.noteBody = self.noteTextView.text; | |
AppDelegate *myAppDelegate = (AppDelegate *) [[UIApplication sharedApplication]delegate]; | |
[myAppDelegate saveContext]; | |
[self.navigationController popViewControllerAnimated:YES]; | |
} | |
#pragma mark - Memory Warning | |
- (void)didReceiveMemoryWarning | |
{ | |
[super didReceiveMemoryWarning]; | |
// Dispose of any resources that can be recreated. | |
} | |
@end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment