본문 바로가기
아이폰 개발/ios 개념&튜토리얼

Ios CoreData 간단한 예제로 배우기

by 인생여희 2020. 7. 30.

ios 코어데이터

 

#.완성된 화면

ViewController : 데이터를 저장하는 화면. 데이터를 입력하고 save를 누르면 코어데이터에 저장이 된다.

 

 

MainViewController : 테이블뷰로 구성되어 있고, 위에서 저장한 데이터가 리스트 형식으로 뿌려진다.

#.스토리 보드

#.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

 

#.모델

image 칼럼만 옵셔널과 allows External storage 를 체크했다.

 

 

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
view raw AppDelegate.h hosted with ❤ by GitHub

 

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
view raw AppDelegate.m hosted with ❤ by GitHub

 

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

 

#.예제파일

CoreDataTest 2.zip
0.07MB

 

'아이폰 개발 > 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