Probleme Magical Record nouvelle version

GregoryGregory Membre
septembre 2014 modifié dans API UIKit #1

Bonjour,


 


Je viens de mettre une appli  à  jour avec la nouvelle version de MR et bizarrement plus rien n'est sauvegardé.


 


Je veux parser mon flux json vider mes entités et les re remplir mais la le NSLog me met bien Save Ok mais count  est a 0.


 


Merci de votre aide ;)


 


En revanche si j'utilise toujours la méthode saveUsingCurrentThreaContextWithBlock (méthode dépréciée) j'obtiens bien un count avec le bon nombre.



NSURLSessionTask *task = [session dataTaskWithURL:[NSURL URLWithString:url] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSDictionary *dictMarque = [dict objectForKey:@Referentiel];
if (!error){
[Marque MR_truncateAll];
[Modele MR_truncateAll];

for (NSDictionary *d in [dictMarque objectForKey:@Marque]) {

Marque *marque = [Marque MR_createEntity];
marque.id = [NSNumber numberWithInteger:[[d objectForKey:@code] intValue]];
marque.name = [d objectForKey:@libelle];
}
for (NSDictionary *d in [dictMarque objectForKey:@Modele]) {

Modele *modele = [Modele MR_createEntity];
modele.id = [NSNumber numberWithInteger:[[d objectForKey:@code] integerValue]];
modele.name = [d objectForKey:@libelle];
Marque *m = [Marque MR_findFirstByAttribute:@id withValue:[d objectForKey:@marque_code]];
modele.modeleMarque = m;
}
[MagicalRecord saveWithBlock:nil completion:^(BOOL success, NSError *error) {
if (error){
NSLog(@Error %@ - %@", error, [error userInfo]);
}
else{
NSLog(@Save OK);
NSLog(@Count %d,[[Marque MR_findAll] count]);

}
}];
}
}];

[task resume];


Mots clés:

Réponses

  • AliGatorAliGator Membre, Modérateur
    septembre 2014 modifié #2

    Et si tu mettais tout ton code Magical (MR_truncateAll + tes 2 boucles for) dans le block à  passer à  "saveWithBlock:" ? (plutôt que de faire les actions avant, et de passer nil comme block ensuite) ?


     


    Car saveWithBlock:completion: son but c'est de créer un childContext, faire les actions de ton block dessus, faire le save de ce childContext dans le defaultContext, et appeler le completion à  la fin.


     


    Or là  tu n'as pas de block (tu as passé nil) donc il crée un childContext, ne fait rien dessus, et le sauve (= merge ce childContext dans le defaultContext)... ce qui ne fait rien puisque tu n'as rien modifié dans ton childContext depuis sa création ! Donc il t'appelle la complexion avec success = YES et error = nil puisqu'il n'y a pas eu d'erreur à  ne rien faire ;)


     


    Et pendant ce temps, toutes les modifications que tu as faites sur ton defaultContext avec le code au dessus (MR_truncateAll + double boucle for), lui, n'est pas sauvé sur le rootSavingContext donc n'est toujours pas en base :-/


     


    Conclusion :


     - Soit tu utilises "saveWithBlock:completion:" comme il est prévu, en mettant le code qui fait les troncations et insertions en base dans le "...withBlock:" " solution que je te conseille


     - Soit tu fais tout directement sur le defaultContext (comme tu as commencé à  faire en mettant ton code MR_truncateAll + 2*for directement à  la racine), mais dans ce cas il faut faire un "[NSManagedObjectContext defaultContext saveWithError:]", si tu veux être cohérent. Mais ce n'est pas la solution que je te conseille car si tu as une erreur dans le parsing ou autre, tu auras alors "corrompu" ton defaultContext en lui ajoutant des entités qui ont des erreurs et ne peuvent pas être sauvées, et ça sera bien moins simple d'annuler le tout pour revenir à  un contexte clean.


     


    Alors qu'avec "saveWithBlock:completion:" et l'utilisation sous-jacente d'un childContext, c'est un peu comme une transaction en SQL ou une branche en GIT, si la transaction / le merge / le save foire, il annule tout au lieu de te laisser dans un état bâtard et corrompu.


  • Merci beaucoup pour ta réponse effectivement ca marche mieux comme ça ;)


    Bizarrement j'avais testé avec mes for dans la methode et cela n'avait pas fonctionné. Enfin bref merci encore.


  • GregoryGregory Membre
    septembre 2014 modifié #4

    Heu... Encore un truc étrange.


     


    Tout fonctionnait correctement et en continuant mes tests j'ai supprimé l'application et maintenant ca re fait comme au début save Ok mais count à  0;


    J'ai corrigé ça 



    [Marque MR_truncateAllInContext:localContext];

    Marque *marque = [Marque MR_createEntityInContext:localContext];

    Et maintenant cela re-fonctionne à  moitié mais je ne sais pas si c'est la bonne méthode.


     


    Autre question:


     


    Lorsque je boucle la 2 fois j'ai besoin de récupérer des infos du context mais il n'y a rien pour le moment car pas encore sauvegardé et je vois pas comment je peux faire.


     


    Merci pour l'aide


     


     


    Et comment puis je faire pour mettre cette partie en initialisation de l'appli?



    NSURLSessionTask *task = [session dataTaskWithURL:[NSURL URLWithString:url] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
    NSDictionary *dictMarque = [dict objectForKey:@Referentiel];
    if (!error){

    [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
    [Marque MR_truncateAll];
    [Modele MR_truncateAll];

    for (NSDictionary *d in [dictMarque objectForKey:@Marque]) {

    Marque *marque = [Marque MR_createEntity];
    marque.id = [NSNumber numberWithInteger:[[d objectForKey:@code] intValue]];
    marque.name = [d objectForKey:@libelle];
    }
    for (NSDictionary *d in [dictMarque objectForKey:@Modele]) {

    Modele *modele = [Modele MR_createEntity];
    modele.id = [NSNumber numberWithInteger:[[d objectForKey:@code] integerValue]];
    modele.name = [d objectForKey:@libelle];
    Marque *m = [Marque MR_findFirstByAttribute:@id withValue:[d objectForKey:@marque_code]];
    modele.modeleMarque = m;
    }

    } completion:^(BOOL success, NSError *error) {
    if (error){
    NSLog(@Error %@ - %@", error, [error userInfo]);
    }
    else{
    NSLog(@Save OK);
    NSLog(@Count %d,[[Marque MR_findAll] count]);
    }
    }];
    }
    }];

    [task resume];

Connectez-vous ou Inscrivez-vous pour répondre.