2013-11-13 5 views
1

Я уже разместил эту проблему, и никто не сказал мне, в чем проблема, пожалуйста, помогите.Основные данные: backgrund context ios

У меня проблема, когда я использую данные Core для сохранения данных в приложении iOS.

Мое приложение может получать много и много текстового сообщения в секунду от сервера.

Так что мне нужно сохранить эти сообщения в моей базе данных, теперь я использую NSOperations внутри очереди для сохранения сообщений (так что вы можете представить число NSOperation в NSOperationQueue).

Проблема в том, что у меня нормальный поток сообщений, тогда он работает нормально, и если есть важный поток сообщений, приложение замораживается бесконечно или NSOperations неограниченно увеличиваются в очереди.

PS: если удалить наблюдателя от слияния сообщения сохраняются без каких-либо проблем

Это мой код из NSOperation:

@interface SaveRecievedMessageOperation() 

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext; 

@property (nonatomic, strong) AppDelegate *appdelegate; 

@property (nonatomic, assign) BOOL executing; 

@property (nonatomic, assign) BOOL finished; 

@end 

@implementation SaveRecievedMessageOperation 

@synthesize message; 
@synthesize managedObjectContext; 
@synthesize appdelegate; 
@synthesize executing; 
@synthesize finished; 



- (id)initWithMessage:(SipMessage *)messageToSave 
{ 
    if (self = [super init]) { 
     self.message = messageToSave; 

    } 
    return self; 
} 

- (void)main 
{ 

    @autoreleasepool 
    { 

     self.appdelegate = [[UIApplication sharedApplication] delegate]; 

     [self managedObjectContext]; 

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

     [self saveMessage]; 


    } 

} 

- (NSManagedObjectContext *)managedObjectContext 
{ 

    if (managedObjectContext != nil) 
    { 

     return managedObjectContext; 

    } 

    NSPersistentStoreCoordinator *coordinator = [self.appdelegate persistentStoreCoordinator]; 
    if (coordinator != nil) { 
     managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
     [managedObjectContext setPersistentStoreCoordinator:coordinator]; 
     [managedObjectContext setMergePolicy:NSOverwriteMergePolicy]; 
    } 
    return managedObjectContext; 
} 

- (void)saveMessage 
{ 

    NSDictionary *header = self.message.headers; 

    NSArray *bodies = self.message.bodies; 

    SipBody *sipBody; 
    NSDictionary* body; 
    NSData *ContentData; 
    if ([[header valueForKey:@"Content-Type"] rangeOfString:@"application/json"].location != NSNotFound) 
    { 
     sipBody = [bodies objectAtIndex:0]; 
     body = [NSJSONSerialization 
       JSONObjectWithData:sipBody.content 
       options:NSJSONReadingAllowFragments 
       error:nil]; 
    } 

    else if ([[header valueForKey:@"Content-Type"] rangeOfString:@"multipart/mixed"].location != NSNotFound) 
    { 
     for (SipBody *sipB in bodies) { 
      if ([[sipB.headers valueForKey:@"Content-Type"] rangeOfString:@"application/json"].location != NSNotFound) 
      { 
       body = [NSJSONSerialization 
         JSONObjectWithData:sipB.content 
         options:NSJSONReadingAllowFragments 
         error:nil]; 
      } 
      else 
      { 
       ContentData = [NSData dataWithData:sipB.content]; 
      } 
     } 
    } 

    else 
    { 
     return; 
    } 
    MGMPhone *sender; 

    NSArray *senders = [self updatePhonesFromMSISDNsList:[[header valueForKey:@"swfrom"] componentsSeparatedByString:MGMseparator]]; 
    sender = senders[0]; 


    NSError *error; 
    MGMMessage *aMesage = [MGMMessage createInContext:self.managedObjectContext]; 
    [aMesage setBoxType:[NSNumber numberWithInteger:BoxTypeIncomingMessage]]; 
    [aMesage setContent:[body valueForKey:@"Content"]]; 
    [aMesage setContentType:[header valueForKey:@"Content-Type"]]; 
    [aMesage setGroupMessage:([[header valueForKey:@"groupmessage"] isEqualToString:@"true"] 
           ? 
    [self saveContext]; 
} 


#pragma mark core data 

- (void)mergeChanges:(NSNotification *)notification 
{ 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      NSManagedObjectContext *mainContext = [appdelegate managedObjectContext]; 
      [mainContext performSelector:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notification]; 


[self setManagedObjectContext:nil]; 

} 

- (void)saveContext 
{ 


    NSError *error = nil; 
    if (self.managedObjectContext != nil) 
    { 
     if ([self.managedObjectContext hasChanges]) { 

      BOOL isSaved = [self.managedObjectContext save:&error]; 
      if(!isSaved){ 

       NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
       abort(); 
      } 
     } 
     else if (![self.managedObjectContext hasChanges]){ 
      [self setManagedObjectContext:nil]; 
     } 
    } 


    } 


@end 

ответ

0

Я думаю, что все в порядке, за исключением операции слияния. Я сам использую очень похожие операции CoreData в фоновом режиме.

Обычно вы хотите объединить обновления из фоновых операций с помощью «основного» контекста управляемых объектов. Поэтому в основном в фоновом режиме вы должны выполнять только метод save:. (Так что не регистрируйтесь для сохранения уведомлений и не инициируйте действия слияния).

Если вам действительно не нужно объединять контексты управляемых объектов в фоновом потоке, уведомление о сохранении должно регистрироваться только один раз в основном потоке (обычно в одноэлементном, например appDelegate или в вашем собственном одиночном режиме). Уведомление о сохранении будет отправлено CoreData после любой операции сохранения в других контекстах, что позволит вам объединить эти изменения с основным контекстом.

Смежные вопросы