본문 바로가기

프로그래밍/iOS,macOS

코어 데이터 정리


헬퍼 클래스를 만들기 위해서 필요한 내용들 정리.



* MO(엔티티) : NSManagedObject

엔티티는 관계형 db의 테이블이라고 보면된다. 

managed object context 는 엔티티를 구현한 객체인 NSManagedObject를 통해 각 엔티티의 데이터를 처리하게 된다.

엔티티는 각각 NSManagedObject 가 되며, 필요시 이를 상속받아 구현하면 된다.

일반적으로 MO 클래스는 엔티티 이름과 동일하게 생성한다.


엔티티 편집화면에서 Editor > Create NSManagedObject Subclass.. 를 클릭하면 모델 클래스를 만들어 준다.

NSManagedObject 객체를 상속받은 클래스를 만들고, 모델 편집화면에서 엔티티 선택후 속성창에서 클래스 이름을 입력해도 된다.


자동생성된 경우 EntityName.m(.h) 파일과 이를 확장한(카테고리) EntityName+CoreDataProperties.m(.h) 파일이 생성된다

스위프트의 경우는  EntityName+CoreDataClass.swift , EntityName+CoreDataProperties.swift 파일이 생성된다.






* 모델만들기(managed object model)

리소스폴더에 dbName.momd 를 생성한다.

dbName.xcdatamodeld 파일이 컴파일되면 리소스폴더의 dbName.momd형태로 들어가게 된다.

해당 파일로 모델 객체를 생성한다.


xcdatamodel 파일에 디자인>데이터모델>모델버전으로 버전을 추가하게 되면, xcdatamodeld로 디렉토리로 변경된다.



// 위해 해당하는 정보로 모델을 생성한다.

// dbName 은 생성한 momd 파일의 이름이다.

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"dbName" withExtension:@"momd"];

NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsURL:modelURL];




* DB파일 저장위치 및 파일명등 정의


// db 파일명

NSString *dbFilename=[NSString stringWithFormat:@"%@.sqlite", @"dbName"];


// 폴더 위치 설정 : NSCachesDirectory, NSLibraryDirectory 등 원하는 path 로 설정한다.

NSString *basePath = 

[NSSearchPathForDirectoriesInDomains( NSCachesDirectory, NSUserDomainMask, YES)        

objectAtIndex:0];



// 추가 경로가 필요한경우 해당 디렉토리를 생성

NSString *dataPath = [basePath stringByAppendingPathComponent:@"DataPath"];


if( ![NSFileManager defaultManage] fileExistsAtPath:dataPath])

{

[[NSFileManager defaultManager] 

createDirectoryAtPath:dataPath

withIntermediateDirectories:NO

attributes:nil

error:nil];

}



// 위 path 문자열에 db파일명을 합친다

NSString *fullPath = [dataPath stringByAppendingPathComponent:dbFileName];


// 해당 전체 path를 url 로 변경

NSURL *dbURL = [NSURL fileURLWithPath:fullPath];






* 모델로부터 저장소 코디네이터 생성(persistent store coordinator)

NSError *error = nil;


// 옵션 : 데이터에 버전정보를 포함해 마이그레이션이 필요한경우 옵션을 설정한다.

NSDictionary *options = 

[NSDictionary dictionaryWithObjectsAndKeys:

[NSNumber numberWithBool:YES] NSMigratePersistentStoresAutomaticallyOption, nil];

[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil)];



코디네이터 생성

// 최초 생성한 모델객체를 사용해 코디네이터를 생성한다.

NSPersistentStoreCoordinator *coord = 

[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];


// 저장소 타입(SQLite) 설정

[coord   addPersistentStoreWithType:NSSQLiteStoreType

configuration:nil

URL:dbURL

options:options

error:&error];


// 해당 위치에 파일이 생성되는데, 이 파일을 백업에서 제외하려면 추가 설정한다

[dbURL setResourceValue:[NSNumber numberWithBool:YES]

forKey:NSURLIsExcludedFromBackupKey

error:&error];




* 컨텍스트생성(managed object context)

컨텍스트와 코디네이터를 연결해 놓고, 사용자는 이 컨텍스트를 통해 db 작업을 하게 된다.


ConcurrencyType : NSPrivateQueueConcurrencyType, NSMainQueueConcurrencyType 

NSMainQueueConcurrencyType은 메인 쓰레드에서 실행되고, NSPrivateQueueConcurrencyType은 performBlock을 통해 실행된다. 백그라운드 처리를 위해서는 NSPrivateQueueConcurrencyType을 사용해야한다. (iOS5 이후)


// 컨텍스트 만들기

NSManagedObjectContext *moContext = 

[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];


// 코디네이터 지정

[moContext setPersistentStoreCoordinator:coord];


// 정책 설정

[moContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];



여기까지 db를 사용하기 위한 기본적인 초기화 과정이 끝났다.




* 데이터 읽기


// 객체 이름

NSString *moName = NSStringFromClass( [MyEntityClass class] );



NSFetchRequest 생성

(두가지 형태가 있는데 둘다  MO 이름이 명시적으로 필요한데, 다른 이유가 무얼까? -_-;)

최근의 xcode 아마도 8.1?? 에서는 MO 객체 생성시 fetchRequest 라는 전역 함수를 만들어 준다.

만들어주는 내용은 2번과 같음.



1. 엔티티명으로 생성

NSFetchRequest *fetchRequest = 

[NSFetchRequest fetchRequestWithEntityName:moName];


2. 단순 생성후 디스크립션 적용

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];


// 엔티티 객체 이름으로 디스크립션 얻기.

NSEntityDescription *entityDesc = 

[NSEntityDescription 

entityForName:moName

inManagedObjectContext:moContext];



Sort / Predicate

NSPredicate *predicate = [ NSPredicate predicateWithFormat:@"조건문" ];

NSSortDescriptor *sd = [[NSSortDescriptor alloc] initWithKey:@"key" ascending:YES];



// 각 정보 설정

[fetchRequest setEntity:entityDesc];

[fetchRequest setSortDescriptors:sd];

[fetchRequest setPredicate:predicate];


// 가져올 값의 개수 설정 :설정하지않으면 전체

fetchRequest.fetchLimit = 1;


// 실행

[moContext executeFetchRequest:fetchRequest error:&error];



// 블럭문을 통한 실행

NSArray *result = nil;

[moContext performBlockAndWait:^{

result = [moContext executeFetchRequest:fetchRequest error:&error];

}];



항목수 가져오기

[moContext countForFetchRequest:fetchRequest error:&error];





* 데이터쓰기


NSManagedObject


NSString *moName = NSStringFromClass( [MyEntityClass class] );

NSEntityDescription *entity = 

[NSEntityDescription 

entityForName:moName

inManagedObjectContext: moContext];


// 오브젝트 객체를 만든다.

NSManagedObject *mo = [[NSMnagedObject alloc] 

initWithEntity:entity 

insertIntoManagedObjectContext: moContext];


// 값 설정

[mo setValue:@"value" forKey:@"key"];


// 저장

[moc save:&error];

'프로그래밍 > iOS,macOS' 카테고리의 다른 글

ChildViewController  (0) 2016.10.27
오토레이아웃 이것저것 / Constraint / UITextView  (0) 2016.10.25
커스텀객체와 인터페이스빌더  (0) 2016.10.23
스토리보드 / XIB  (0) 2016.10.22
싱글톤  (0) 2016.10.19
슬라이드메뉴  (0) 2016.10.16
UITableView / UICollectionView  (0) 2016.10.16
파일 가져오기  (0) 2016.10.16
뷰 에니메이션  (0) 2016.10.13
비동기 처리 ( GCD , NSOperation )  (0) 2016.10.13