2013-10-23 43 views
0

我在使用核心數據在我的iOS應用中保存數據時遇到了問題。核心數據塊NSoperation

我的應用程序可以在一秒內從服務器接收許多和許多文本消息。

所以我需要將這些消息保存在我的數據庫中,現在我在隊列中使用NSOperations來保存消息(因此您可以想象NSOperationQueue中NSOperation的數量)。

問題出在一些指令後,我把NSOperationQueue阻塞了,NSOperation的數量沒有限制地增加了。

隨着一些調查,我發現問題是保存上下文,保存上下文阻止NSOperation和NSOperation我永遠不會結束,它將永遠不會出列,但我無法解決它。

中的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 

這是一個共享實例。

#import "CoreDataService.h" 

static CoreDataService *sharedService = nil; 


@implementation CoreDataService 
@synthesize coreDataReceptionQueue; 

+ (id)sharedService 
{ 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     if (sharedService == nil) sharedService = [[self alloc] init]; 
    }); 
    return sharedService; 
} 


- (NSOperationQueue*) coreDataReceptionQueue 
{ 
    if (coreDataReceptionQueue) 
    { 
     return coreDataReceptionQueue; 
    } 
    coreDataReceptionQueue = [[NSOperationQueue alloc] init]; 
    [coreDataReceptionQueue setMaxConcurrentOperationCount:1]; 
    return coreDataReceptionQueue; 
} 
@end 

,這我怎麼添加在iPad上一個新的操作

SaveRecievedMessageOperation *op = [[SaveRecievedMessageOperation alloc]initWithMessage:message]; 
     [[[CoreDataService sharedService] coreDataReceptionQueue] addOperation:op]; 
+0

顯示NSOperationQueue的代碼 – Patel

+0

coreDataReceptionQueue = [[NSOperationQueue alloc] init]; [coreDataReceptionQueue setMaxConcurrentOperationCount:1]; – Bacem

+0

你在哪寫這個代碼意味着在哪個方法? – Patel

回答

0

我想讀這是一個有點困難。它不會出現你正在將信息包裝到'執行...'塊中的moc - 你必須這樣做。另外,您也可以在這些中執行saveContext。使用異步執行塊保存信息並保存,並同步讀取。

0

這可能不是一個答案,但是這是我的觀察:

1)你初始化你的操作方面有:NSPrivateQueueConcurrencyType這將迫使你使用上下文,像這樣:
[context performBlockAndWait:^{/*you code*/}](你使用「等待」,因爲你不希望你的操作過早完成)。如果你沒有你的操作可能會掛起......

==>你可以使用NSConfinementConcurrencyType並留下您的代碼是解決這一

2)您使用的操作隊列的「最大併發」這是感染一個串行隊列。
您可以簡單地持有一個NSPrivateQueueConcurrencyType上下文,並在其上發出[context performBlock:^{/*your code*/}]以實現相同的效果。