Skip to content

Instantly share code, notes, and snippets.

@keicoder
Created March 13, 2014 04:47
Show Gist options
  • Save keicoder/9522023 to your computer and use it in GitHub Desktop.
Save keicoder/9522023 to your computer and use it in GitHub Desktop.
objective-c : Note with Core Data (SwiftNote5)
//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