2013-12-22 2 views
0

Я пытаюсь сохранить данные в основные данные после завершения веб-запроса. В AppDelegate У меня есть мой контекст. В дальнейшем код для получения контекста:Основные данные не сохраняют данные до закрытия приложения

- (NSManagedObjectContext *)contex { 
    @synchronized(self) { 
     if (_contex == nil) { 
      _contex = [[NSManagedObjectContext alloc] init]; 
      [_contex setPersistentStoreCoordinator:self.persistentStoreCoordinator]; 
     } 
     return _contex; 
    } 
} 

Как руководства Apple, говорит, у меня есть один настойчивый магазин coordinata совместно с несколькими контекстами.

Это код, в котором я беру данные из Интернета, получаю контекст и вызываю метод для сохранения нового значения в основные данные.

NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL *localFile, NSURLResponse *response, NSError *error) { 
      [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 
      UIImage *image; 
      if (!error) { 
       NSData *imageData = [NSData dataWithContentsOfURL:localFile]; 
       image = [UIImage imageWithData:imageData]; 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        [[NSNotificationCenter defaultCenter] postNotificationName:@"thumbnailIsSetted" object:self userInfo:@{@"image": image, 
                                  @"PhotoUrl": photo.url}]; 
        @synchronized(self) { 
         NSManagedObjectContext *context = [(SocialMapAppDelegate *)[[UIApplication sharedApplication] delegate] contex]; 
         [Photo addThumbnailData:imageData toPicture:photo.url fromContext:context]; 
        } 
       }); 
      } else { 
       //if we get an error, we send the default icon 
       image = [UIImage imageNamed:@"Photo-thumbnail"]; 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        [[NSNotificationCenter defaultCenter] postNotificationName:@"thumbnailIsSetted" object:self userInfo:@{@"cached image": image, 
                                  @"PhotoUrl": photo.url}]; 
       }); 
      } 
     }]; 
     [task resume]; //we resume the task in case it is souspended 
    }]; 

и это метод, который я использую для сохранения данных в основных данных:

+ (void)addThumbnailData:(NSData *)data toPicture:(NSString *)pictureUrl fromContext:(NSManagedObjectContext *)context 
{ 
    if (pictureUrl && context) { 
     NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Photo"]; 
     request.predicate = [NSPredicate predicateWithFormat:@"url == %@",pictureUrl]; 
     NSError *error = nil; 
     NSArray *matches = [context executeFetchRequest:request error:&error]; 
     if ([matches count] == 1) { 
      Photo *photo = [matches lastObject]; 
      photo.thumbnailData = data; 

      if (![context save:&error]) { 
       NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
      } 
     } 
    } 
} 

Я не могу понять, где проблема, контекст не ноль, и я не» t получить любую ошибку. Если я перезапущу приложение, там будут данные.

+0

Какое значение [соответствует счету] возвращается? –

+0

Где вы собираетесь обновлять данные в пользовательском интерфейсе? –

ответ

0

код выглядит нормально ... сохранение сохраняет содержимое контекста на диске в порядке. обновить другие контексты вы должны слушать уведомления ContextDidSave и объединить в данных

первого наблюдения:

... 
[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(mergeChanges:) 
              name:NSManagedObjectContextDidSaveNotification 
              object:managedObjectContext];    
... 

затем объединить

- (void)mergeChanges:(NSNotification *)notification { 
    // Merge changes into the main context on the main thread 
    [self.mainManagedObjectContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) 
    withObject:notification 
waitUntilDone:YES]; 
} 
+0

не работает. уведомление вызывается, но не имеет эффекта –

+0

вы вызываете mergeChangesFromContextDidSaveNotification в правильном контексте? и он не сливается? ..также, конечно, вы должны обновить свой интерфейс после завершения слияния. –

+0

да, контекст прав, и слияние выполняется, но когда я обновляю представление и снова отправляю запрос на основные данные, это не имеет никакого эффекта , и данные снова загружаются из интернета –

1

Я не рекомендую использовать несколько контекстов, если вы не используя многопоточную конструкцию в вашем приложении. Я бы рекомендовал отключить приложение до одного контекста, чтобы избежать необходимости передавать уведомления. Это просто не нужно 99% времени.

Кроме того, если вы используете родительские/дочерние контексты, я не рекомендую повторно использовать дочерние контексты. Они должны быть временными; используется для одной задачи, а затем выбрасывается. Причина этого заключается в том, что изменения данных только поступают в одну сторону; вверх. Если вы что-то меняете в одном ребенке, его не подталкивают ни к одному из братьев и сестер. Кроме того, детские контексты устаревают. Если вы внесете изменения в основной контекст, все дети будут устаревшими.

Ваш пользовательский интерфейс должен использовать один NSManagedObjectContext по всему приложению. Это, скорее всего, решит ваши проблемы.

+0

, но я читаю в этой теме, [link] (http://stackoverflow.com/questions/6622699/singleton-managedobjectcontext), которые имеют один единственный NSManagedObjectContext во всем приложении, является плохой практикой. –

+0

Я решил проблему, большое вам спасибо за ваше время! –

+0

эта ссылка говорит что-то совсем другое. это препятствует тому, чтобы vcs получал контекст. им следует передать контекст => увеличить повторное использование –

0

я решил, что проблема была в классе, где я Визуализируйте и попросить данных, в этом классе вместо получить контекст от AppDelegate на этом пути:

[(SocialMapAppDelegate *)[[UIApplication sharedApplication] delegate] contex]; 

я сделал это

[[SocialMapAppDelegate alloc] init].contex 

таким образом я просто создать еще один контекст и другой магазин, вещь, которая совершенно неправильно, поэтому я решил просто заменить код выше

[(SocialMapAppDelegate *)[[UIApplication sharedApplication] delegate] contex]; 
Смежные вопросы