
#.완성된 화면


#.스토리 보드

#.coredata 경로확인 및 로깅 방법
1.Edit Scheme 선택
2.Run 선택
3.Arguments탭 선택
4.제일 윗부분(Argument passed on launch)에 아래 옵션 추가
-com.apple.CoreData.SQLDebug 1
-com.apple.CoreData.Logging.stderr 1
#.출력 결과
CoreData: annotation: Connecting to sqlite database file at "/Users/hyunhojeong/Library/Developer/CoreSimulator/Devices/DFF6EC41-3141-49E9-B3EF-54D24F416C31/data/Containers/Data/Application/8648D6DB-21FD-4FCF-9CBC-1ECE02D2A2FF/Library/Application Support/CoreDataTest.sqlite"
CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'
CoreData: sql: pragma recursive_triggers=1
CoreData: sql: pragma journal_mode=wal
CoreData: sql: SELECT Z_VERSION, Z_UUID, Z_PLIST FROM Z_METADATA
CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'
CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_MODELCACHE'
CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'ACHANGE'
CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'ATRANSACTIONSTRING'
CoreData: sql: BEGIN EXCLUSIVE
CoreData: sql: SELECT Z_MAX FROM Z_PRIMARYKEY WHERE Z_ENT = ?
CoreData: sql: UPDATE OR FAIL Z_PRIMARYKEY SET Z_MAX = ? WHERE Z_ENT = ? AND Z_MAX = ?
CoreData: sql: pragma auto_vacuum
CoreData: annotation: sql execution time: 0.0003s
CoreData: sql: pragma auto_vacuum=2
CoreData: annotation: sql execution time: 0.0003s
CoreData: sql: COMMIT
CoreData: sql: BEGIN EXCLUSIVE
CoreData: sql: INSERT INTO ZPERSON(Z_PK, Z_ENT, Z_OPT, ZAGE, ZFIRSTNAME, ZIMAGE, ZLASTNAME) VALUES(?, ?, ?, ?, ?, ?, ?)
CoreData: sql: INSERT INTO ZPERSON(Z_PK, Z_ENT, Z_OPT, ZAGE, ZFIRSTNAME, ZIMAGE, ZLASTNAME) VALUES(?, ?, ?, ?, ?, ?, ?)
CoreData: sql: INSERT INTO ZPERSON(Z_PK, Z_ENT, Z_OPT, ZAGE, ZFIRSTNAME, ZIMAGE, ZLASTNAME) VALUES(?, ?, ?, ?, ?, ?, ?)
CoreData: sql: COMMIT
CoreData: sql: pragma page_count
CoreData: annotation: sql execution time: 0.0001s
CoreData: sql: pragma freelist_count
CoreData: annotation: sql execution time: 0.0001s
#.모델

AppDelegate.h
#import <UIKit/UIKit.h> | |
#import <CoreData/CoreData.h> | |
@interface AppDelegate : UIResponder <UIApplicationDelegate> | |
@property (strong, nonatomic) UIWindow *window; | |
//컨테이너 프로퍼티 | |
@property (readonly, strong) NSPersistentContainer *persistentContainer; | |
- (void)saveContext; | |
@end | |
AppDelegate.m
//코어 데이터 헤더파일 import | |
#import "Person+CoreDataClass.h" | |
#import "AppDelegate.h" | |
@interface AppDelegate () | |
// 영구저장소 컨테이너를 프로퍼티로 선언한다. | |
@property (nonatomic) NSManagedObjectContext *context; | |
@end | |
@implementation AppDelegate | |
//코어데이터 CRUD 테스트 | |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { | |
self.context = [self.persistentContainer viewContext]; | |
//데이터 추가 | |
//[self createData]; | |
//데이터 조회 | |
//[self basicFetch]; | |
//데이터 정렬 조회 | |
//[self fetchWithSort]; | |
//데이터 조건 조회 | |
//[self fetchWithFilter]; | |
//업데이트 | |
//[self updatePersons]; | |
//삭제 | |
//[self deletePerson]; | |
return YES; | |
} | |
//데이터 생성 - 저장 (데이터를 객체형태로 만들어서 db에 저장할 수 있다.) | |
-(void)createData{ | |
//컨텍스트로 객체 초기화 | |
Person *p1 = [[Person alloc]initWithContext:self.context]; | |
p1.firstName = @"kang"; | |
p1.lastName = @"yougkyuen"; | |
p1.age = 30; | |
//컨텍스트로 객체 초기화 | |
Person *p2 = [[Person alloc]initWithContext:self.context]; | |
p2.firstName = @"kim"; | |
p2.lastName = @"eunjoo"; | |
p2.age = 33; | |
//컨텍스트로 객체 초기화 | |
Person *p3 = [[Person alloc]initWithContext:self.context]; | |
p3.firstName = @"song"; | |
p3.lastName = @"wonyil"; | |
p3.age = 30; | |
//저장 | |
[self saveContext]; | |
} | |
//데이터 조회 | |
-(void)basicFetch{ | |
//테이블 객체 생성 | |
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"]; | |
//컨텍스트로 조회 예) [컨텍스트 : 테이블 객체 인자 ] | |
NSArray<Person*>* persons = [self.context executeFetchRequest:request error:nil]; | |
//출력 | |
[self printResultsFromArray:persons]; | |
} | |
//데이터 정렬 조회 | |
-(void) fetchWithSort{ | |
//엔터티 | |
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"]; | |
//정렬 설정 객체 : 정렬기준 칼럼 , YES : 오름차순 NO : 내림차순 | |
NSSortDescriptor *ageDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES]; | |
//정렬 설정 | |
request.sortDescriptors = @[ ageDescriptor ]; | |
//컨텍스트에 조회 요청 | |
NSArray <Person *>* persons = [self.context executeFetchRequest:request error:nil]; | |
//출력 | |
[self printResultsFromArray:persons]; | |
} | |
//데이터 조건 조회 | |
-(NSArray <Person*>*)fetchWithFilter{ | |
//테이블 객체 생성 | |
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"]; | |
//조회 조건 설정 | |
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age > 32"]; | |
request.predicate = predicate; | |
//조회 | |
NSArray <Person*>* persons = [self.context executeFetchRequest:request error:nil]; | |
//출력 | |
[self printResultsFromArray:persons]; | |
return persons; | |
} | |
//업데이트 - 특정 칼럼의 데이터 수정하기 | |
-(void)updatePersons{ | |
//배열의 0번째 객체의 age 를 10 으로 변경 | |
Person *personOne = [self fetchWithFilter][0]; | |
personOne.age = 10; | |
[self saveContext]; | |
} | |
//삭제 - | |
-(void)deletePerson{ | |
//배열의 0번째 객체 삭제 | |
Person *somePerson = [self fetchWithFilter][0]; | |
[[self context]deleteObject:somePerson]; | |
[self saveContext]; | |
} | |
//배열 -> 출력 | |
-(void)printResultsFromArray:(NSArray <Person*>*) persons{ | |
for (Person *person in persons) { | |
NSLog(@"first name : %@" , [person firstName]); | |
NSLog(@"last name : %@" , [person lastName]); | |
NSLog(@"age: %d" , [person age]); | |
} | |
} | |
//앱종료될때 | |
- (void)applicationWillTerminate:(UIApplication *)application{ | |
[self saveContext]; | |
} | |
#pragma mark - Core Data stack | |
//macOS Sierra로 업데이트되면서 코어데이터에 NSPersistentContainer 클래스가 추가되었다. | |
//이 클래스를 사용하면 코어데이터 스택을 셋업하는 여러 귀찮은 과정을 생략하고 간단하게 처리할 수 있다. | |
@synthesize persistentContainer = _persistentContainer; | |
- (NSPersistentContainer *)persistentContainer { | |
// 영구저장소 컨테이너 초기화 | |
@synchronized (self) { | |
if (_persistentContainer == nil) { | |
// Managed Model의 이름을 기준으로 구성할 수 있다. | |
// 이 때, 이름에는 확장자를 생략해야 한다. | |
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"CoreDataTest"]; | |
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) { | |
if (error != nil) { | |
NSLog(@"Unresolved error %@, %@", error, error.userInfo); | |
abort(); | |
} | |
}]; | |
} | |
} | |
return _persistentContainer; | |
} | |
#pragma mark - Core Data Saving support | |
- (void)saveContext { | |
//위에 프로퍼티로 지정해놓았음. | |
//NSManagedObjectContext *context = self.persistentContainer.viewContext; | |
NSError *error = nil; | |
if ([self.context hasChanges] && ![self.context save:&error]) { | |
NSLog(@"Unresolved error %@, %@", error, error.userInfo); | |
abort(); | |
} | |
} | |
@end |
MainViewController.h
#import <UIKit/UIKit.h> | |
NS_ASSUME_NONNULL_BEGIN | |
//테이블 뷰 | |
@interface MainViewController : UIViewController | |
@end | |
NS_ASSUME_NONNULL_END |
MainViewController.m
//테이블 뷰 | |
#import "MainViewController.h" | |
#import "Person+CoreDataClass.h" | |
@import CoreData; | |
#import "AppDelegate.h" | |
#import "ViewController.h" | |
//UITableViewDataSource 추가, Main.storyboard 에서 tableView 우클릭 후 위쪽 네모에 놓고 dataSource 선택하기. | |
@interface MainViewController ()<UITableViewDataSource> | |
//테이블 뷰 | |
@property (strong, nonatomic) IBOutlet UITableView *tableView; | |
@property (nonatomic) NSArray <Person*>* persons; | |
@property (nonatomic) NSManagedObjectContext *context; | |
@property (nonatomic,weak) AppDelegate *delegate; | |
@end | |
@implementation MainViewController | |
- (void)viewDidLoad { | |
[super viewDidLoad]; | |
NSLog(@"### viewDidLoad 호출"); | |
//델리게이트와 컨텍스트 초기화 | |
self.delegate = ((AppDelegate *)[[UIApplication sharedApplication]delegate]); | |
self.context = self.delegate.persistentContainer.viewContext; | |
} | |
//화면이 나타날때 조회 + 테이블 뷰 데이터 다시 로드 | |
-(void)viewWillAppear:(BOOL)animated{ | |
NSLog(@"### viewWillAppear 호출"); | |
[super viewWillAppear:animated]; | |
[self fetchAllPersons]; | |
[self.tableView reloadData]; | |
} | |
//데이터 전체조회 | |
-(void)fetchAllPersons{ | |
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"]; | |
self.persons = [self.context executeFetchRequest:request error:nil]; | |
} | |
//테이블 row 수 | |
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ | |
return self.persons.count; | |
} | |
//테이블 셀 내용 | |
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ | |
//cell | |
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; | |
//data | |
Person *person = self.persons[indexPath.row]; | |
cell.textLabel.text = person.lastName; | |
cell.detailTextLabel.text = person.firstName; | |
return cell; | |
} | |
// + 버튼 눌렀을때 호출 | |
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ | |
NSLog(@"### prepareForSegue 호출"); | |
//ViewController(저장화면) 반환함 | |
//ViewController(저장화면) 객체에 context, delegate 삽입 | |
ViewController *mvc = segue.destinationViewController; | |
mvc.context = self.context; | |
mvc.delegate = self.delegate; | |
} | |
@end |
ViewController.h
//데이터 저장 화면 controller | |
#import <UIKit/UIKit.h> | |
@import CoreData; | |
@class AppDelegate; | |
@interface ViewController : UIViewController | |
@property (nonatomic) NSManagedObjectContext *context; | |
@property (nonatomic, weak) AppDelegate *delegate; | |
@end | |
ViewController.m
#import "ViewController.h" | |
#import "Person+CoreDataClass.h" | |
#import "AppDelegate.h" | |
@interface ViewController () | |
@property (strong, nonatomic) IBOutlet UITextField *firstNameTextField; | |
@property (strong, nonatomic) IBOutlet UITextField *lastNameTextField; | |
@property (strong, nonatomic) IBOutlet UITextField *ageTextField; | |
@end | |
@implementation ViewController | |
- (void)viewDidLoad { | |
[super viewDidLoad]; | |
// Do any additional setup after loading the view. | |
} | |
//저장 | |
- (IBAction)save:(id)sender { | |
NSString *fn = self.firstNameTextField.text; | |
NSString *ln = self.lastNameTextField.text; | |
int16_t age = (int16_t)[self.ageTextField.text intValue]; | |
//객체에 컨텍스트를 이용해서 초기화 | |
Person *person = [[Person alloc]initWithContext:self.context]; | |
person.firstName = fn; | |
person.lastName = ln; | |
person.age = age; | |
[self.delegate saveContext]; | |
} | |
@end |
#.예제파일
'아이폰 개발 > ios 개념&튜토리얼' 카테고리의 다른 글
ios 위변조 탐지 로직 (1) | 2020.08.05 |
---|---|
Ios push 기초 with Firebase (1) | 2020.08.01 |
SQLite 응용 (0) | 2020.07.29 |
SQLite 기초 (0) | 2020.07.29 |
Firebase를 이용해서 좌표 저장 후 지도에 표시 (0) | 2020.07.29 |