Pergunta

No momento, estou atualizando um aplicativo para usar Core Data.O aplicativo que você poderia dizer é um "visualizador de banco de dados", apenas um banco de dados pode ser visualizado por vez.Cada banco de dados é mantido em sua própria pasta separada.Atualmente os dados são baixados e armazenados como um conjunto de arquivos plist.

Na nova versão, preciso converter esses bancos de dados plist em armazenamentos Core Data (um armazenamento para cada banco de dados). Já configurei os métodos que criam os arquivos de armazenamento separados e criam as entidades.O problema é que todas as entidades são salvas no primeiro banco de dados que criei, não no arquivo "atual" ou "último criado".

O processo básico que estou usando é:

//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];
}

Como alguém alternaria corretamente entre lojas, essencialmente "redefinindo" tudo entre cada troca.De preferência (se possível) usando registro mágico.

EDITAR:Descobri uma parte do problema e removi a maior parte do comportamento indesejado.Acontece que você não pode ligar de forma confiável [MagicalRecord cleanUp] em um tópico de fundo.Além disso, não está fazendo o que acho que deveria (veja abaixo).Acabei ligando de volta para o thread principal após cada "salvar" para redefinir a pilha do Core Data.Isso cria um novo contexto para os três primeiros bancos de dados.depois disso, duplica o contexto do banco de dados três bancos de dados atrás.Portanto, os mesmos três contextos são usados ​​em um loop.

Isto é o que tenho atualmente;Eu inicio o processo criando um thread em segundo plano e executo o código para criar um único banco de dados em segundo plano:

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

Em seguida, criando a pilha e o banco de dados:

- (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];
    });

Em seguida, redefina tudo e repita para todos os bancos de dados:

- (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];
        });
    }
}

Com os dois NSLogs, recebo isto no console:(usando seis bancos de dados, o padrão é o mesmo, não importa quantos bancos de dados eu converta.)

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

E [MagicalRecord cleanUp] não está fazendo o que diz que está fazendo.Aqui está o que o método deve fazer.

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

Mas acontece que o NSStoreCoordinator toda vez que eu salvo, é o mesmo coordenador, no mesmo local de memória, e cada loja fica por aí.Algo não está funcionando direito...

Foi útil?

Solução 2

Acontece que o problema que estou tendo é devido a um bug no MagicalRecord.Enviei um problema do git aqui: https://github.com/magicalpanda/MagicalRecord/issues/270

Outras dicas

MagicalRecord pode não ser a melhor ferramenta para este trabalho para você...

Primeiro, vamos corrigir o uso do setupCoreDataStackWithStoreNamed:método.O parâmetro usa um NSString, não um URL, nem um caminho de arquivo.MagicalRecord escolherá o caminho adequado para você e criará sua loja lá.seu arquivo sqlite resultante provavelmente será nomeado com o caminho que você pretendia.

A seguir, você precisará criar dinamicamente seu modelo CoreData para este arquivo.Isso é meio difícil, mas possível.Você precisará percorrer esses arquivos plist e interpretar entidades, atributos e relacionamentos, e criar NSEntityDescriptions, NSAttributeDescriptions e NSRelationshipDesctiptions correspondentes e preencher um NSManagedObjectModel "manualmente".Você vai querer procurar o método

- [NSManagedObjectModel setEntities:(NSArray *)]

bem como os métodos de criação para NSEntityDescription, NSAttributeDescription e NSRelationshipDescription.

Você também vai querer salvar esse modelo em algum lugar para não precisar recriá-lo todas as vezes.Felizmente, ele está em conformidade com o NSCoding, então você poderá salvá-lo no disco.

Depois disso, você provavelmente desejará preencher seus dados.A partir daqui, MagicalRecord pode ajudá-lo.Sugiro olhar para o Importação de dados facilitada postagem no blog para a qual escrevi Cacau é minha namorada

Se você quiser "trocar de armazenamento", o que eu acho que significa que você deseja criar um novo armazenamento para cada arquivo plist que você possui, então você terá que destruir toda a pilha do Core Data para cada arquivo.Se você conseguir usar o MagicalRecord para este projeto, você precisará dar uma olhada em [MagicalRecord cleanUp] e começar de novo.Se cada modelo fosse igual, você poderia liberar seu Coordenador de Loja Persistente e criar um novo para sua loja.Mas como seus “esquemas” provavelmente serão diferentes, você só vai querer riscar tudo e começar de novo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top