2012-12-10 32 views
0

我在我的核心數據應用程序中添加了一些名爲Transaction的對象。這些交易鏈接到一個賬戶。核心數據併發性 - 集合在枚舉時發生了變化

我想在保存所有交易時更新帳戶金額。有時,併發異常

「收藏突變而被枚舉」

accountManagedObjectWithId方法NSArray *matches = [managedObjectContext executeFetchRequest:request error:&error];線。

//TransactionsManager 

- (BOOL)addRepeatTransaction:(Transaction *)transaction{ 

    Account *accountTrx = transaction.account; 
    double accountAmount = accountTrx.amount; 
    for (int i =0; i<nbRepeat; i++){ 
     accountAmount +=transactionBiz.amount; 
     [[Persister instance] registerTransaction:transaction]; 
    } 
    [[Persister instance]editAmountAccount:transaction.account amount:accountAmount]; 
    [[Persister instance]saveContext]; 

    return YES; 
} 

//Persister 

-(id)init { 
    if (self = [super init]){ 
     managedObjectContext = [appDelegate managedObjectContext]; 
     return self; 
    } 
    return nil; 
} 

-(BOOL)registerTransaction:(Transaction *)transaction { 
    TransactionManagedObject *transactionsRow = (TransactionsManagedObject *)[NSEntityDescription insertNewObjectForEntityForName:@"Transactions" inManagedObjectContext:managedObjectContext]; 

    transactionsRow.idTransaction = [NSNumber numberWithInt:transaction.idTransaction]; 
    transactionsRow.name = transaction.name; 
    transactionsRow.amount = [NSNumber numberWithDouble:transaction.amount]; 
    [...] 
    transactionsRow.account = [[Finder instance] accountManagedObjectWithId:transaction.account.idAccount]; 

    return YES; 
} 

-(BOOL)editAmountAccount:(Account *)asset amount:(double)amount { 
    AccountManagedObject *accountRow = [[Finder instance] accountManagedObjectWithId:account.idAccount]; 

    accountRow.amount = [NSNumber numberWithDouble:amount]; 
    return YES; 
} 

-(AccountManagedObject *)accountManagedObjectWithId:(NSInteger)idAccount { 

    NSFetchRequest *request = [[NSFetchRequest alloc]init]; 
    [request setEntity:[NSEntityDescription entityForName:@"Accounts" inManagedObjectContext:managedObjectContext]]; 

    //Predicate 
    NSString *recordedIdAccount = @"idAccount"; 
    NSNumber *numberIdAccount = [NSNumber numberWithInt:idAccount]; 
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", recordedIdAccount,numberIdAccount]; 
    [request setPredicate:predicate]; 

    //Execute 
    NSError *error; 
    NSArray *matches = [managedObjectContext executeFetchRequest:request error:&error]; 
    NSInteger nbResult = [matches count]; 
    if(nbResult==1){ 
     return [matches objectAtIndex:0]; 
    } 
    if(nbResult==0){ 
     [...] 
     return nil; 
    } 
    if(nbResult>0){ 
     [...] 
     return nil; 
    } 
    return nil; 
} 

//UI call 
[...] 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 
    //Save 
    [[TransactionsManager instance] addRepeatTransaction:transactionToAdd]; 

    dispatch_async(dispatch_get_main_queue(), ^{ 

      //Call the delegate 
      [self.delegate theSaveButtonOnTheAddTransactionTVCWasTapped:self]; 
     }); 
}); 

@Valentin拉杜

我已經試過了,但問題仍然存在。我必須爲每次添加設置一個managedObjectContext。這是行得通的,但會降低應用程序的速度。這是正確的做法嗎?

-(BOOL)registerTransaction:(Transaction *)transaction{ 
    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init]; 
    [moc setPersistentStoreCoordinator:[[self managedObjectContext] persistentStoreCoordinator]]; 


    TransactionsManagedObject *transactionsRow = (TransactionsManagedObject *)[NSEntityDescription insertNewObjectForEntityForName:@"Transactions" inManagedObjectContext:moc]; 

    transactionsRow.idTransaction = [NSNumber numberWithInt:transaction.idTransaction]; 
    transactionsRow.name = transaction.name; 
    transactionsRow.amount = [NSNumber numberWithDouble:transaction.amount]; 
    [...] 
    transactionsRow.account = [[Finder instance] accountManagedObjectWithId:transaction.account.idAccount andManagedContext:moc]]; 

    NSError *error = nil; 
    if (![moc save:&error]) { 
     [[ErrorManager instance] addError:error]; 
     return NO; 
    } 

    return YES; 
} 
+0

你能提供一個自包含的答案嗎?這裏的細節太多了。你的後臺線程在哪裏?謝謝。 –

回答

5

您似乎只使用一個上下文,如果您在覈心數據對象上執行並行操作,那麼這是錯誤的。每個線程應有一個上下文,並在每次保存時合併上下文。 Apple的核心數據指南更詳細地討論了這一點。

+0

我試過了,但問題依然存在。我必須爲每次添加設置一個managedObjectContext。這是行得通的,但會降低應用程序的速度。這是正確的做法嗎? – Alexandre

+0

是的,它工作。我的錯誤是我嘗試過你的解決方案,但沒有以正確的方式,所以我認爲它不是在開火。如果我錯了,請糾正我,但是backgroundManagedContext必須在第二個線程上使用AND創建,並且不能在主線程上創建並在第二個線程上使用? – Alexandre

+0

我認爲現在沒問題。非常感謝您的答覆! – Alexandre

相關問題