SORU
10 AĞUSTOS 2010, Salı


&; Toplama numaralandırılmış" olurken; executeFetchRequest üzerinde mutasyona uğramış oldu"

Saat için bir sorun kapalı ve stackoverflow (ve her tavsiyeleri bulundu uygulanır) bu konuda her şeyi okumak zorunda değilim, artık resmi olarak yardım için ihtiyacım var. ;o)

Burada bağlam :

İPhone projemde arka plan üzerinde veri alma ve yönetilen nesne bağlamda eklemek istiyorum. Öneriler burada bulunan şu, burada ne işim var

  • Ana moc kaydedin
  • Sürekli mağaza Koordinatörü ana moc tarafından kullanılan bir arka plan moc başlatılamadı
  • Arka plan moc NSManagedObjectContextDidSaveNotification bildirim gözlemci olarak benim denetleyicisi kayıt
  • Bir arka plan iş parçacığı üzerinde alma yöntemi
  • Her zaman veri, arka plan moc eklemek alındı
  • Tüm veriler alındıktan sonra, arka plan moc kaydedin
  • Ana konu üzerindeki ana moc değişiklikleri birleştirme
  • Bildirim için bir gözlemci olarak benim denetleyicisi kurtulun
  • Reset ve arka plan moc bırakın

Bazen (ve rastgele), özel...

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x5e0b930> was mutated while being enumerated...

...arka plan üzerinde executeFetchRequest moc aradığımda atılır, eğer alınan verilerin veritabanında olup olmadığını kontrol etmek için. Alma yöntemi dışında çalışan bir şey olmadığından set mutasyona ne olduğunu merak ediyorum.

Benim denetleyicisi ve test benim varlık (projem bu iki sınıf ve değiştirilmemiş olan app temsilci, oluşan) tüm kod ekledim :

//
//  RootViewController.h
//  FK1
//
//  Created by Eric on 09/08/10.
//  Copyright (c) 2010 __MyCompanyName__. All rights reserved.
//


#import <CoreData/CoreData.h>

@interface RootViewController : UITableViewController <NSFetchedResultsControllerDelegate> {
    NSManagedObjectContext *managedObjectContext;
    NSManagedObjectContext *backgroundMOC;
}


@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain) NSManagedObjectContext *backgroundMOC;

@end


//
//  RootViewController.m
//  FK1
//
//  Created by Eric on 09/08/10.
//  Copyright (c) 2010 __MyCompanyName__. All rights reserved.
//


#import "RootViewController.h"
#import "FK1Message.h"

@implementation RootViewController

@synthesize managedObjectContext;
@synthesize backgroundMOC;

- (void)viewDidLoad {
    [super viewDidLoad];

    self.navigationController.toolbarHidden = NO;

    UIBarButtonItem *refreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshAction:)];

    self.toolbarItems = [NSArray arrayWithObject:refreshButton];
}

#pragma mark -
#pragma mark ACTIONS

- (void)refreshAction:(id)sender {
    // If there already is an import running, we do nothing

    if (self.backgroundMOC != nil) {
        return;
    }

    // We save the main moc

    NSError *error = nil;

    if (![self.managedObjectContext save:&error]) {
        NSLog(@"error = %@", error);

        abort();
    }

    // We instantiate the background moc

    self.backgroundMOC = [[[NSManagedObjectContext alloc] init] autorelease];

    [self.backgroundMOC setPersistentStoreCoordinator:[self.managedObjectContext persistentStoreCoordinator]];

    // We call the fetch method in the background thread

    [self performSelectorInBackground:@selector(_importData) withObject:nil];
}

- (void)_importData {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

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

    FK1Message *message = nil;

    NSFetchRequest *fetchRequest = nil;
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"FK1Message" inManagedObjectContext:self.backgroundMOC];
    NSPredicate *predicate = nil;
    NSArray *results = nil;

    // fake import to keep this sample simple

    for (NSInteger index = 0; index < 20; index  ) {
        predicate = [NSPredicate predicateWithFormat:@"msgId == %@", [NSString stringWithFormat:@"%d", index]];

        fetchRequest = [[[NSFetchRequest alloc] init] autorelease];

        [fetchRequest setEntity:entity];
        [fetchRequest setPredicate:predicate];

        // The following line sometimes randomly throw the exception :
        // *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x5b71a00> was mutated while being enumerated.

        results = [self.backgroundMOC executeFetchRequest:fetchRequest error:NULL];

        // If the message already exist, we retrieve it from the database
        // If it doesn't, we insert a new message in the database

        if ([results count] > 0) {
            message = [results objectAtIndex:0];
        }
        else {
            message = [NSEntityDescription insertNewObjectForEntityForName:@"FK1Message" inManagedObjectContext:self.backgroundMOC];
            message.msgId = [NSString stringWithFormat:@"%d", index];
        }

        // We update the message

        message.updateDate = [NSDate date];
    }

    // We save the background moc which trigger the backgroundMOCDidSave: method

    [self.backgroundMOC save:NULL];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:self.backgroundMOC];

    [self.backgroundMOC reset]; self.backgroundMOC = nil;

    [pool drain];
}

- (void)backgroundMOCDidSave:(NSNotification*)notification {    
    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(backgroundMOCDidSave:) withObject:notification waitUntilDone:YES];
        return;
    }

    // We merge the background moc changes in the main moc

    [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}

@end

//
//  FK1Message.h
//  FK1
//
//  Created by Eric on 09/08/10.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import <CoreData/CoreData.h>

@interface FK1Message :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString * msgId;
@property (nonatomic, retain) NSDate * updateDate;

@end

// 
//  FK1Message.m
//  FK1
//
//  Created by Eric on 09/08/10.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import "FK1Message.h"

@implementation FK1Message 

#pragma mark -
#pragma mark PROPERTIES

@dynamic msgId;
@dynamic updateDate;

@end

Bunların hepsi ! Tüm bu proje. Hiçbir tablo, hiçbir NSFetchedResultsController, arka plan moc veri alma arka plan iş parçacığı dışında başka bir şey görmek.

Bu durumda set mutasyona ne olabilir ?

Bariz olan bir şeyi kaçırıyorum eminim ve bu beni deli ediyor. Birisi bu konuda bana yardım edebileceğini umuyorum.

Önceden, teşekkürler

Eric.

DÜZENLEME :

İşte tam yığın izleme :

    2010-08-10 10:29:11.258 FK1[51419:1b6b] *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x5d075b0> was mutated while being enumerated.<CFBasicHash 0x5d075b0 [0x25c6380]>{type = mutable set, count = 0,
entries =>
}
'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x0255d919 __exceptionPreprocess   185
    1   libobjc.A.dylib                     0x026ab5de objc_exception_throw   47
    2   CoreFoundation                      0x0255d3d9 __NSFastEnumerationMutationHandler   377
    3   CoreData                            0x02287702 -[NSManagedObjectContext executeFetchRequest:error:]   4706
    4   FK1                                 0x00002b1b -[RootViewController _fetchData]   593
    5   Foundation                          0x01d662a8 -[NSThread main]   81
    6   Foundation                          0x01d66234 __NSThread__main__   1387
    7   libSystem.B.dylib                   0x9587681d _pthread_start   345
    8   libSystem.B.dylib                   0x958766a2 thread_start   34
)
terminate called after throwing an instance of 'NSException'

CEVAP
10 AĞUSTOS 2010, Salı


TAMAM, sorunumu çözdüm ve Fred Mccann'ın bu blog yazısı için teşekkür etmeliyim sanırım

http://www.duckrowing.com/2010/03/11/using-core-data-on-multiple-threads/

Bu sorun, arka plan iş parçacığı yerine ana iş parçacığı arka plan benim moc ben örneğini gerçeği geliyor. Apple her iş parçacığı kendi moc olması gerektiğini söylediğinde, ciddiye almak gerekir : her moc bunu kullanarak iplik örneği olmalı !

Aşağıdaki satırları geliyor

// We instantiate the background moc

self.backgroundMOC = [[[NSManagedObjectContext alloc] init] autorelease];

[self.backgroundMOC setPersistentStoreCoordinator:[self.managedObjectContext persistentStoreCoordinator]];

..._importData yöntem bildirimi için gözlemci olarak denetleyicisi kaydetmek için önce () sorunu çözer.

Yardımın için teşekkürler Peter. Ve Fred McCann için teşekkürler değerli blog yazısı için.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • gadgetgal38

    gadgetgal38

    9 HAZİRAN 2009
  • Jeremy Stark

    Jeremy Stark

    23 Mayıs 2010
  • Whizzpopping

    Whizzpopping

    10 Kasım 2005