여러 번의 패스를 통해 핵심 데이터 마이그레이션에 대한 예 또는 설명?
제 아이폰 앱은 핵심 데이터 저장소를 마이그레이션해야 하고, 일부 데이터베이스는 꽤 큽니다.애플의 문서는 메모리 사용을 줄이기 위해 데이터를 마이그레이션하기 위해 "복수 패스"를 사용할 것을 제안합니다.그러나 설명서가 매우 제한적이고 실제로 이 작업을 수행하는 방법을 잘 설명하지 못합니다.누군가 저에게 좋은 예를 보여주거나, 실제로 이 일을 해내는 과정을 자세히 설명해 줄 수 있을까요?
저는 애플이 그들의 문서에서 암시하는 것이 무엇인지 알아냈습니다.그것은 사실 매우 쉽지만, 분명해지려면 갈 길이 멉니다.예를 들어 설명을 설명하겠습니다.초기 상황은 이렇습니다.
데이터 모델 버전 1
'핵심 데이터 저장이 가능한 내비게이션 기반 앱' 템플릿으로 프로젝트를 만들 때 얻을 수 있는 모델입니다.나는 그것을 컴파일하고 포루프의 도움을 받아 몇 가지 다른 값을 가진 약 2,000개의 엔트리를 만들기 위해 약간의 하드 히트를 했습니다.NSDate 값을 가진 2,000개의 이벤트가 있습니다.
이제 다음과 같은 두 번째 버전의 데이터 모델을 추가합니다.
데이터 모델 버전 2
차이점은 다음과 같습니다.이벤트 개체는 사라졌고, 두 개의 새 개체가 생겼습니다.것.double
.NSString
.
목표는 모든 버전 1 이벤트를 두 개의 새 엔티티로 전송하고 마이그레이션에 따라 값을 변환하는 것입니다.이렇게 하면 값이 각각 다른 개체의 다른 유형으로 두 배가 됩니다.
마이그레이션하기 위해서는 수작업으로 마이그레이션을 선택하고 매핑 모델을 사용합니다.이것 또한 당신의 질문에 대한 답변의 첫 부분입니다.2,000개 항목을 마이그레이션하는 데 시간이 오래 걸리고 메모리 사용량을 낮게 유지하는 것이 좋기 때문에 두 단계로 마이그레이션을 수행합니다.
이 매핑 모델을 더 분할하여 엔티티 범위만 마이그레이션할 수도 있습니다.우리가 100만개의 기록을 가지고 있다고 치자, 이것은 모든 과정을 망치게 할 수도 있습니다.필터 술어를 사용하여 가져온 도면요소를 좁힐 수 있습니다.
다시 두 개의 매핑 모델로 돌아갑니다.
우리는 다음과 같은 첫 번째 매핑 모델을 만듭니다.
1. 새 파일 -> 리소스 -> 매핑 모델
2. 이름을 고르면 1단계를 선택했습니다.
3. 소스 및 대상 데이터 모델 설정
매핑 모델 1단계
다중 패스 마이그레이션에는 사용자 정의 엔티티 마이그레이션 정책이 필요 없지만, 이 예에 대한 세부 정보를 좀 더 얻기 위해 이 작업을 수행합니다.그래서 엔티티에 사용자 지정 정책을 추가합니다.이는 항상 의 하위 클래스입니다.
이 정책 클래스는 마이그레이션을 실현하기 위한 몇 가지 방법을 구현합니다.하지만 이 경우에는 간단하기 때문에 한 가지 방법만 구현해야 합니다.
구현은 다음과 같습니다.
StepOne Entity 마이그레이션 정책.
#import "StepOneEntityMigrationPolicy.h"
@implementation StepOneEntityMigrationPolicy
- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance
entityMapping:(NSEntityMapping *)mapping
manager:(NSMigrationManager *)manager
error:(NSError **)error
{
// Create a new object for the model context
NSManagedObject *newObject =
[NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName]
inManagedObjectContext:[manager destinationContext]];
// do our transfer of nsdate to nsstring
NSDate *date = [sInstance valueForKey:@"timeStamp"];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
// set the value for our new object
[newObject setValue:[dateFormatter stringFromDate:date] forKey:@"printedDate"];
[dateFormatter release];
// do the coupling of old and new
[manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping];
return YES;
}
마지막 단계: 마이그레이션 자체
거의 동일한 두 번째 매핑 모델을 설정하는 부분은 생략하겠습니다, 시간만.1970년부터 NSD 날짜를 두 배로 변환하는 데 사용된 Interval Since.
마지막으로 우리는 이주를 시작해야 합니다.일단 보일러 플레이트 코드는 생략하겠습니다.필요하시면 여기에 올리겠습니다.마이그레이션 프로세스 사용자 정의에서 확인할 수 있습니다. 처음 두 코드 예제를 병합한 것일 뿐입니다.세 번째 부분과 마지막 부분은 다음과 같이 수정됩니다.클래스의 클래스 메소드를 사용하는 대신 번들에서 처음 발견된 매핑 모델 중 하나만 반환하기 때문에 을 사용합니다.
이제 두 가지 매핑 모델이 있습니다. 이 모델은 루프의 모든 경로에서 사용할 수 있으며 마이그레이션 방법을 마이그레이션 관리자에게 전송할 수 있습니다.바로 그겁니다.
NSArray *mappingModelNames = [NSArray arrayWithObjects:@"StepOne", @"StepTwo", nil];
NSDictionary *sourceStoreOptions = nil;
NSURL *destinationStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataMigrationNew.sqlite"];
NSString *destinationStoreType = NSSQLiteStoreType;
NSDictionary *destinationStoreOptions = nil;
for (NSString *mappingModelName in mappingModelNames) {
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:mappingModelName withExtension:@"cdm"];
NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:fileURL];
BOOL ok = [migrationManager migrateStoreFromURL:sourceStoreURL
type:sourceStoreType
options:sourceStoreOptions
withMappingModel:mappingModel
toDestinationURL:destinationStoreURL
destinationType:destinationStoreType
destinationOptions:destinationStoreOptions
error:&error2];
[mappingModel release];
}
메모들
매핑 모델은 다음과 같이 끝납니다.
cdm
대상 저장소를 제공해야 하며 원본 저장소가 되어서는 안 됩니다.마이그레이션이 성공한 후 이전 이름을 삭제하고 새 이름을 변경할 수 있습니다.
매핑 모델을 생성한 후 데이터 모델을 약간 변경했는데, 이로 인해 호환성 오류가 발생하여 매핑 모델을 다시 생성해야만 해결할 수 있었습니다.
다음 질문과 관련이 있습니다.
iPhone의 대규모 CoreData 데이터스토어를 마이그레이션하는 데 메모리 문제
iOS를 사용한 청크에서 여러 패스 코어 데이터 마이그레이션
첫 번째 링크 인용하기
이는 "Multiple Passes" 섹션의 공식 문서에서 설명하지만, 이들이 제안하는 접근 방식은 개체 유형별로 마이그레이션을 나누는 것, 즉 전체 데이터 모델에서 개체 유형의 하위 집합을 마이그레이션하는 여러 매핑 모델을 만드는 것처럼 보입니다.
데이터베이스 스키마에 5개의 엔티티(예: 개인, 학생, 과정, 수업, 등록)가 있다고 가정해 보면, 학생은 개인을 서브클래스하고, 수업은 과정을 구현하며, 등록은 수업과 학생에 합류합니다.이러한 모든 테이블 정의를 변경한 경우 기본 클래스에서 시작하여 작업을 진행해야 합니다.따라서 등록 기록마다 수업과 학생 수에 따라 달라지기 때문에 등록 전환부터 시작할 수 없습니다.따라서 사용자 테이블만 마이그레이트하고, 기존 행을 새 테이블로 복사하고, 가능한 경우 새 필드를 작성한 후 제거된 열을 폐기하는 것부터 시작합니다.각 마이그레이션을 자동 릴리스 풀 안에서 수행하면 메모리가 다시 시작되도록 할 수 있습니다.
사용자 테이블이 완료되면 학생 테이블을 다시 변환할 수 있습니다.그런 다음 [과정]으로 이동한 다음 [수업], 마지막으로 [등록] 테이블로 이동합니다.
다른 고려 사항은 레코드 수입니다. 만약 비슷한 사람이 천 개의 행을 가지고 있다면, 100개 정도마다 릴리스에 해당하는 NSManagedObject를 실행해야 하는데, 이는 관리되는 개체 컨텍스트를 알려주는 것입니다 [moc refreshObject:obmergeChanges:아니오]; 오래된 데이터 타이머를 매우 낮게 설정하여 메모리가 자주 지워지도록 합니다.
언급URL : https://stackoverflow.com/questions/5995231/example-or-explanation-of-core-data-migration-with-multiple-passes
'programing' 카테고리의 다른 글
워드프레스의 발췌문을 "더" 링크와 함께 사용하시겠습니까? (0) | 2023.10.12 |
---|---|
왜 괜찮은 sql 파서가 없습니까? (0) | 2023.10.12 |
메뉴가 여러 개일 때 li의 메뉴에 페이지 ID가 손실됨 (0) | 2023.10.07 |
최대 절전 모드 4 업그레이드 후 "찾았습니다: 비트, 예상: 부울" (0) | 2023.10.07 |
MariaDB: 단일 미러 DB와 다중 로컬 DB를 가진 슬레이브 (0) | 2023.10.07 |