문제

현재 Core Data를 사용하도록 앱을 업데이트하고 있습니다.당신이 말할 수 있는 앱은 "데이터베이스 뷰어"이며, 한 번에 하나의 데이터베이스만 볼 수 있습니다.각 데이터베이스는 별도의 폴더에 보관됩니다.현재 데이터는 plist 파일 세트로 다운로드되어 저장됩니다.

새 버전에서는 이러한 plist 데이터베이스를 핵심 데이터 저장소(각 데이터베이스당 하나의 저장소)로 변환해야 합니다. 별도의 저장소 파일을 생성하고 엔터티를 생성하는 방법을 이미 설정했습니다.문제는 모든 엔터티가 "현재" 또는 "마지막으로 생성된" 파일이 아니라 내가 만든 첫 번째 데이터베이스에 저장된다는 것입니다.

내가 사용하는 기본 프로세스는 다음과 같습니다.

//For each database {
//Create the sqlite file and set up NSManagedObjectContext
[MagicalRecord setupCoreDataStackWithStoreNamed:
    [NSURL fileURLWithPath:
    [NSString stringWithFormat:@"%@/%@/%@.sqlite",
    dirPath, directory, directory]]];
NSManagedObjectContext *managedObjectContext = 
    [NSManagedObjectContext MR_contextForCurrentThread];

//Iterate through all the plist files and create the necessary entities.
//Save new entities to file
[managedObjectContext MR_save];
//Clean up all cashes
[MagicalRecord cleanUp];
}

상점 간을 적절하게 전환하는 방법은 기본적으로 각 스위치 사이의 모든 것을 "재설정"하는 것입니다.(가능하다면) 마법 기록을 사용하는 것이 좋습니다.

편집하다:문제의 일부를 발견하고 원치 않는 동작을 대부분 제거했습니다.당신은 안정적으로 전화를 걸 수 없다는 것이 밝혀졌습니다 [MagicalRecord cleanUp] 백그라운드 스레드에서.또한 내가 생각하는 대로 작동하지 않습니다(아래 참조).나는 핵심 데이터 스택을 재설정하기 위해 각 "저장" 후에 메인 스레드를 다시 호출하게 되었습니다.이렇게 하면 처음 세 개의 데이터베이스에 대한 새 컨텍스트가 생성됩니다.그 후에는 3개 데이터베이스 이전의 데이터베이스에서 컨텍스트를 복제합니다.따라서 동일한 세 가지 컨텍스트가 루프에 사용됩니다.

이것이 제가 현재 갖고 있는 것입니다.백그라운드 스레드를 생성하여 프로세스를 시작하고 코드를 실행하여 백그라운드에서 단일 데이터베이스를 생성합니다.

backgroundQueue = dispatch_queue_create("com.BrandonMcQuilkin.myQueue", NULL);
    dispatch_async(backgroundQueue, ^(void) {
        [self createSQLiteDatabase:updateList];
    });

그런 다음 스택과 데이터베이스를 생성합니다.

- (void)createSQLiteDatabase:(NSArray *)updateList
{
    NSString *directory = [updateList objectAtIndex:0];
    [MagicalRecord setupCoreDataStackWithStoreNamed:
        [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@/%@.sqlite",
        dirPath, directory, directory]]];
    NSManagedObjectContext *managedObjectContext = 
        [NSManagedObjectContext MR_contextForCurrentThread];
    //Check to see if the stack has reset
    NSLog(@"Before:%i", [[Competition MR_findAllInContext:managedObjectContext] count]);

    //Create and add entities to context...

    //Prepare for next loop
    NSLog(@"After:%i", [[Competition MR_findAllInContext:managedObjectContext] count]);
    [managedObjectContext MR_saveNestedContexts];
    [NSManagedObjectContext MR_resetContextForCurrentThread];

    NSMutableArray *temp = [[NSMutableArray alloc] initWithArray:updateList];
    [temp removeObjectAtIndex:0];

    dispatch_async(dispatch_get_main_queue(), ^(void){
        [self shouldContinueUpdating:temp];
    });

그런 다음 모든 것을 재설정하고 모든 데이터베이스에 대해 반복하십시오.

- (void)shouldContinueUpdating:(NSArray *)databases
{
    //preform cleanup on main thread and release background thread
    [MagicalRecord cleanUp];
    dispatch_release(backgroundQueue);

    if ([databases count] != 0) {
        backgroundQueue = dispatch_queue_create("com.BrandonMcQuilkin.myQueue", NULL);
        dispatch_async(backgroundQueue, ^(void) {
            [self createSQLiteDatabase:databases];
        });
    }
}

두 개의 NSLog를 사용하면 콘솔에 다음이 표시됩니다.(6개의 데이터베이스를 사용하면 몇 개의 데이터베이스를 변환하더라도 패턴은 동일합니다.)

//First Loop
Before:0
After:308
//Second Loop
Before:0
After:257
//Third Loop
Before:0
After:37
//Fourth Loop
Before:308 
After:541 
//Fifth Loop
Before:257
After:490
//Sixth Loop
Before:37
After:270
... Keep adding to each of the three contexts.

그리고 [MagicalRecord cleanUp] 하고 있는 일을 하고 있지 않습니다.메소드가 수행해야 하는 작업은 다음과 같습니다.

+ (void) cleanUpStack;
{
[NSManagedObjectContext MR_cleanUp];
[NSManagedObjectModel MR_setDefaultManagedObjectModel:nil];
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:nil];
[NSPersistentStore MR_setDefaultPersistentStore:nil];
}

하지만 저장할 때마다 NSStoreCoordinator는 동일한 메모리 위치에 있는 동일한 코디네이터이며 각 상점이 돌아다니는 것으로 나타났습니다.뭔가 작동이 잘 안되네요...

도움이 되었습니까?

해결책 2

제가 겪고 있는 문제는 MagicalRecord의 버그 때문인 것으로 나타났습니다.여기에 git 문제를 제출했습니다. https://github.com/magicalpanda/MagicalRecord/issues/270

다른 팁

MagicalRecord는 이 작업에 가장 적합한 도구가 아닐 수도 있습니다...

먼저 setupCoreDataStackWithStoreNamed의 사용법을 수정해 보겠습니다.방법.매개변수는 URL이나 파일 경로가 아닌 NSString을 사용합니다.MagicalRecord는 귀하에게 적합한 경로를 선택하고 거기에 상점을 생성합니다.결과 sqlite 파일은 의도한 경로로 이름이 지정될 가능성이 높습니다.

다음으로 이 파일에 대한 CoreData 모델을 동적으로 생성해야 합니다.이것은 다소 힘들지만 가능합니다.이러한 plist 파일을 탐색하고 엔터티, 속성 및 관계를 해석하고 해당 NSEntityDescriptions, NSAttributeDescriptions 및 NSRelationshipDesctiptions를 생성하고 NSManagedObjectModel을 "수동으로" 채워야 합니다.당신은 방법을 찾고 싶을 것입니다

- [NSManagedObjectModel setEntities:(NSArray *)]

NSEntityDescription, NSAttributeDescription 및 NSRelationshipDescription에 대한 생성 방법도 있습니다.

또한 매번 다시 만들 필요가 없도록 이 모델을 어딘가에 저장하는 것이 좋습니다.다행히 NSCoding을 준수하므로 디스크에 저장만 하면 됩니다.

그 후에는 데이터를 채우고 싶을 것입니다.여기에서 MagicalRecord가 도움을 드릴 수 있습니다.나는 간편한 데이터 가져오기 내가 쓴 블로그 게시물 코코아는 내 여자친구

"스토어 전환"을 원하면(이는 가지고 있는 각 plist 파일에 대해 새 스토어를 생성하려는 경우) 각 파일에 대한 전체 핵심 데이터 스택을 해체해야 한다는 의미입니다.이 프로젝트에 MagicalRecord를 사용하게 된다면 [MagicalRecord cleanUp]을 살펴보고 다시 시작해야 합니다.각 모델이 동일한 경우 영구 스토어 코디네이터를 출시하고 스토어에 새 모델을 생성하면 됩니다.그러나 "스키마"가 다를 수 있으므로 모든 것을 긁고 다시 시작하고 싶을 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top