2014-09-12 35 views
16

Şimdi birkaç günlüğüne bu sorunu yaşıyorum ve gerçekten sinir bozucu .. Kodumu tekrar tekrar gözden geçirdim farklı bir şeyi denedim ve aynı sorun .. Bu, her zaman değil zamanların sadece% 50'si olur. BuTemel Veriler: hata: Çekirdek Veri değişimi sırasında istisna yakalandı

Sorun,

Hep ayrıştırma dosyaların 2 iyi gider benim Çekirdek veri, 3 CSV dosyaları veri ayrıştırma ediyorum ama orta/saniye dosya nerede .. zorlaştırır Kilitlenme her zaman olur, bu dosya için bu dosya ve managedObjectContext sınıfının adresi olacaktır.

Hata Mesajı

CoreData: error: Serious application error. 
Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. 
-[__NSCFSet addObject:]: attempt to insert nil with userInfo (null) 
2014-09-12 11:27:06.115 AppName[210:3907] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFSet addObject:]: attempt to insert nil' 

Yani, benim FetchData sınıfta ben farklı şekillerde sorunu çözmek için çalışıyoruz.

  • İlk olarak, .csv dosyasını değiştirdim ve boş olan tüm alanlara/hücrelere N/A ekledim.
  • İkincisi, bu bir değere sahip değilse, N/A kaydedin, benim FetchData sınıfında bir giriş yapıyorum.
  • Üçüncüsü, Verileri ayrıştırma işlemini gerçekleştirdiğim görünüm denetleyicimde, artık Temel Verilerimde bu 3 varlık için üç farklı özellik ayrıldı.

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContextGI;

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContextVA;

Biraz deli ya da her türlü olabilir ama gerçekten o, hep iyi düşünecek Buna olası bir çözüm veya yaklaşım çalışırken, bu nedenle bu düzeltmek gerekir. ayrıştırmayı gerçekleştirmek için işlevler çağrılmasına

ViewController .. Bu tasarruf boş olsaydı çek gerçekleştirdikten Hangi .. böylece benim Çekirdek Veri modeli fonksiyonları ve

//at the beginning of my model 
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 

-(IBAction)myLoadingTask:(id)sender{ 

     dispatch_async(kBgQueue, ^{ 

      NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 

      NSString *savedValue = @""; 

      if([[userDefaults stringForKey:@"dataFetched"] length] > 0){        
       savedValue = [userDefaults stringForKey:@"dataFetched"]; 
      } 

      // if the csv files data hasn't been fetch it, then fetch it 
      if([savedValue length] == 0){ 

       FetchData *fd = [[FetchData alloc] initWithManagedContext:self.managedObjectContext]; 

       // fetching benefits data 
       [fd beginParser]; 

       FetchGIBillData *fdGI = [[FetchGIBillData alloc] initWithManagedContext:self.managedObjectContextGI]; 

       // fetching gi bill data 
       [fdGI beginParser]; 

       FetchVAPhones *fdVA = [[FetchVAPhones alloc] initWithManagedContext:self.managedObjectContextVA]; 

       // fetching va phones 
       [fdVA beginParser]; 

       NSString *valueToSave = @"saved"; 
       [[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:@"dataFetched"]; 
       [[NSUserDefaults standardUserDefaults] synchronize]; 

      } 

     }); 
} 

olduğunu N/böylece benim varlık olan tüm özellikleri dizeleri

#define GIBILL_FILENAME @"gi_bill_data" 

int numOfEntries; 
- (id)initWithManagedContext:(NSManagedObjectContext*)managedObjectContext 
{ 
    self.managedObjectContext = managedObjectContext; 
    arrayOfRecords = [[NSMutableArray alloc] init]; 
    numOfEntries=0; 
    return self; 
} 


- (void) beginParser 
{ 
    if (self.managedObjectContext == nil){ 
     // Error: Must pass in NSManagedObjectContext 
     return; 
    } 

    NSString *filePath = [[NSBundle mainBundle] pathForResource:GIBILL_FILENAME ofType:@"csv"]; 
    NSInputStream *stream = [NSInputStream inputStreamWithFileAtPath:filePath]; 
    NSStringEncoding encoding = NSUTF8StringEncoding;//NSWindowsCP1250StringEncoding; 

    CHCSVParser *parser = [[CHCSVParser alloc] initWithInputStream:stream usedEncoding:&encoding delimiter:',']; 
    parser.delegate = self; 

    [parser parse]; 

    // uncomment to update data x amount of dates 
    //[self checkDateForRefreshCSV:parser]; 

} 

* vardır .. bir ve * Bu tasarruf gerçekleştiği yer! *

#pragma mark - Data Add 
/** 
* addRows 
* @param parser: the CHCSV parser that will parse if required refresh 
* @brief: add the row to ths managedObjectContent DB. All values saved. 
*/ 
- (void) addRows:(CHCSVParser *)parser 
{ 
    int i = -1; 
    if ([arrayOfRecords count] == 0) return; 
    GIBill *data = [NSEntityDescription 
         insertNewObjectForEntityForName:@"GIBill" 
         inManagedObjectContext:self.managedObjectContext]; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.facility_code = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.facility_code = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.institution = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.institution = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.city = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.city = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.state = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.state = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.country = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.country = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.bah = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.bah = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.poe = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.poe = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.yr = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.yr = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.gibill = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.gibill = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 0) 
     data.cross = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.cross = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.grad_rate = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.grad_rate = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.grad_rate_rank = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.grad_rate_rank = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.default_rate = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.default_rate = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.avg_stu_loan_debt = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.avg_stu_loan_debt = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.avg_stu_loan_debt_rank = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.avg_stu_loan_debt_rank = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.indicator_group = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.indicator_group = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.salary = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.salary = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.zip = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.zip = @"N/A"; 

    if([[arrayOfRecords objectAtIndex:++i] length] > 2) 
     data.ope = [arrayOfRecords objectAtIndex:i]; 
    else 
     data.ope = @"N/A"; 

    NSError *error; 

    [self.managedObjectContext save:&error]; 

} 

Sanırım konunun düşünüyorum en alakalı kodunu yayınlanmıştır. Lütfen başka bir konuya ihtiyaç duyuyorsanız veya sorun hakkında daha fazla bilgi varsa lütfen bana bildirin.

Şimdiden teşekkürler!

+0

eklenti istisna mola noktaları ve boş ekleme nerede kontrol edin. –

+0

Bir çok soruna neden olacak eski Çekirdek Veri eşzamanlılık modelini kullanarak iş parçacıklarında bu bağlamlara erişiyorsunuz. – quellish

+0

Eski çekirdek veri eşzamanlılık modeliyle ne demek istiyorsun? @quellish – NorthBlast

cevap

20

Eh, tüm sorun, NSManagedObjectContext ve Main Thread öğesindeki her şeyi oluşturmak ve daha sonra erişmek veya Background Thread içinde kullanmaktı.

Yani, sadece this post takip ettim ve şimdi her şey gerçekten doğru yönde beni koy yorumlar için pürüzsüz :)

Çok teşekkürler mükemmel çalışıyor ve ve o ben edebilmek için gerekli tamamen neydi sorunu bul ..

Teşekkürler! Sonra AppDelegate.h

+ (NSManagedObjectContext *)mainQueueContext; 
+ (NSManagedObjectContext *)privateQueueContext; 

yılında

, benim AppDelegate.m içinde

#pragma mark - Singleton Access 

+ (NSManagedObjectContext *)mainQueueContext 
{ 
    return [self mainQueueContext]; 
} 

+ (NSManagedObjectContext *)privateQueueContext 
{ 
    return [self privateQueueContext]; 
} 

#pragma mark - Getters 

- (NSManagedObjectContext *)mainQueueContext 
{ 
    if (!_mainQueueContext) { 
     _mainQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
     _mainQueueContext.persistentStoreCoordinator = self.persistentStoreCoordinator; 
    } 

    return _mainQueueContext; 
} 

- (NSManagedObjectContext *)privateQueueContext 
{ 
    if (!_privateQueueContext) { 
     _privateQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
     _privateQueueContext.persistentStoreCoordinator = self.persistentStoreCoordinator; 
    } 

    return _privateQueueContext; 
} 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(contextDidSavePrivateQueueContext:) 
                name:NSManagedObjectContextDidSaveNotification 
                object:[self privateQueueContext]]; 
     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(contextDidSaveMainQueueContext:) 
                name:NSManagedObjectContextDidSaveNotification 
                object:[self mainQueueContext]]; 
    } 
    return self; 
} 

#pragma mark - Notifications 

- (void)contextDidSavePrivateQueueContext:(NSNotification *)notification 
{ 
    @synchronized(self) { 
     [self.mainQueueContext performBlock:^{ 
      [self.mainQueueContext mergeChangesFromContextDidSaveNotification:notification]; 
     }]; 
    } 
} 

- (void)contextDidSaveMainQueueContext:(NSNotification *)notification 
{ 
    @synchronized(self) { 
     [self.privateQueueContext performBlock:^{ 
      [self.privateQueueContext mergeChangesFromContextDidSaveNotification:notification]; 
     }]; 
    } 
} 

- (void)dealloc 
{ 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
} 

Ve son olarak benim viewController ben işlerim gönderiyorum yılında background ..

// dont forget the macro 
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 

dispatch_async(kBgQueue, ^{ 

    id delegate = [[UIApplication sharedApplication] delegate]; 
    self.managedObjectContext = [delegate privateQueueContext]; 

    // do something in the background with your managedObjectContext!!!! 

}); 
Sadece özel olarak eşzamanlılık türünü ayarlamak zorunda

_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 

:

+0

Neden kamu yöntemini oluşturdunuz? '+ (NSManagedObjectContext *) privateQueueContext' örnek yöntemini kullandığınızda' id delegate = [[UIApplication sharedApplication] temsilci]; ' ' self.managedObjectContext = [delege privateQueueContext]; ' – TheMall

+0

nasıl hızlı 3? – Taprolano

+0

@Taprolano, 3. adımda bunu anladınız mı? –

21

hat aşağıda günümü kurtardı. Bu şekilde, veritabanı üzerinde eş zamanlı olarak özel sıralar üzerinde birden çok işlem gerçekleştirebilir.

+1

Bu, diğer tüm Çekirdek Veri işlevleri ile uygulamanızınDelegate'ında bulunabilir. Swift için bu satır: var managedObjectContext = NSManagedObjectContext (concurrencyType: .PrivateQueueConcurrencyType). Bu yazıya tüm kredi yazar. Parlak yakalama ve gündüz koruyucu. –

+0

Vay muhteşem, mükemmel çalışıyor +30 – Claudio

1
Swift 3'te bunu yapıyor insanlar için

:

var managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)

İlgili konular