2010-04-01 152 views
2

這是從之前在一個完全不同的主題觸及前面一個問題的重點更明確的版本。殘破的多線程核心數據

我正在使用多線程的可可核心數據應用程序。有一首歌和藝術家;每首歌都有一位藝術家的關係。這裏沒有引用委託代碼文件;它或多或少看起來像XCode生成的模板。

我比前者更好地處理前者的技術,任何多線程功能都來自Core Data模板。當我用一種方法完成我所有的ManagedObjectContext工作時,我很好。當我將提取或插入然後返回對象工作放入單獨的方法中時,應用程序會暫停(但不會崩潰)新方法的return語句,如下所示。新方法甚至獲得自己的MOC是安全的,並沒有任何幫助。結果是Song的一個增加,並且在生成Artist之後停止。

我沒有得到任何錯誤或例外,我不知道爲什麼。我已經調試出了wazoo。我的理論是發生的任何錯誤都出現在另一個線程中,而我正在觀察的錯誤正在等待某件事。

我對getArtistObject有什麼問題:以及如何解決?謝謝。

- (void)main 
{ 
    NSInteger songCount = 1; 
    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init]; 
    [moc setPersistentStoreCoordinator:[[self delegate] persistentStoreCoordinator]]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:moc]; 

/* songDict generated here */ 

    for (id key in songDict) 
    { 
     NSManagedObject *song = [NSEntityDescription insertNewObjectForEntityForName:@"Song" inManagedObjectContext:moc]; 
     [song setValue:[songDictItem objectForKey:@"Name"] forKey:@"title"]; 
     [song setValue:[self getArtistObject:(NSString *) [songDictItem objectForKey:@"Artist"]] forKey:@"artist"]; 

     [songDictItem release]; 

     songCount++; 
    } 

    NSError *error; 
    if (![moc save:&error]) 
    [NSApp presentError:error]; 

    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:moc]; 
    [moc release], moc = nil; 
    [[self delegate] importDone]; 
} 

- (NSManagedObject*) getArtistObject:(NSString*)theArtist 
{ 
    NSError *error = nil; 
    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init]; 
    [moc setPersistentStoreCoordinator:[[self delegate] persistentStoreCoordinator]]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:moc]; 

    NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease]; 
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Artist" inManagedObjectContext:moc]; 
    [fetch setEntity:entityDescription]; 

    // object to be returned 
    NSManagedObject *artistObject = [[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc]; 

    // set predicate (artist name) 
    NSPredicate *pred = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"name = \"%@\"", theArtist]]; 
    [fetch setPredicate:pred]; 

    NSArray *response = [moc executeFetchRequest:fetch error:&error]; 

    if (error) 
    [NSApp presentError:error]; 

    if ([response count] == 0) // empty resultset --> no artists with this name 
    { 
    [artistObject setValue:theArtist forKey:@"name"]; 
    NSLog(@"%@ not found. Adding.", theArtist); 

    return artistObject; 
    } 
    else 
    return [response objectAtIndex:0]; 
} 

@end 
+0

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/Concurrency.html – 2017-04-21 22:35:46

回答

0

嘗試鎖定管理對象上下文,你訪問它之前,你用它做後再次解鎖它:

- (void)main 
{ 
    NSInteger songCount = 1; 
    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init]; 
    [moc lock]; 
    [moc setPersistentStoreCoordinator:[[self delegate] persistentStoreCoordinator]]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:moc]; 
    [moc unlock]; 

/* songDict generated here */ 

    for (id key in songDict) 
    { 
     [moc lock]; 
     NSManagedObject *song = [NSEntityDescription insertNewObjectForEntityForName:@"Song" inManagedObjectContext:moc]; 
     [moc unlock]; 
     [song setValue:[songDictItem objectForKey:@"Name"] forKey:@"title"]; 
     [song setValue:[self getArtistObject:(NSString *) [songDictItem objectForKey:@"Artist"]] forKey:@"artist"]; 

     [songDictItem release]; 

     songCount++; 
    } 

    NSError *error; 
    [moc lock]; 
    if (![moc save:&error]) 
    [NSApp presentError:error]; 
    [moc unlock]; 

    [moc lock]; 
    [[NSNotificationCenter defaultCenter] removeObserver:self name:NSManagedObjectContextDidSaveNotification object:moc]; 
    [moc unlock]; 
    [moc release], moc = nil; 
    [[self delegate] importDone]; 
} 

- (NSManagedObject*) getArtistObject:(NSString*)theArtist 
{ 
    NSError *error = nil; 
    NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init]; 
    [moc lock]; 
    [moc setPersistentStoreCoordinator:[[self delegate] persistentStoreCoordinator]]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:moc]; 
    [moc unlock]; 

    NSFetchRequest *fetch = [[[NSFetchRequest alloc] init] autorelease]; 
    [moc lock]; 
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Artist" inManagedObjectContext:moc]; 
    [moc unlock]; 
    [fetch setEntity:entityDescription]; 

    // object to be returned 
    [moc lock]; 
    NSManagedObject *artistObject = [[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc]; 
    [moc unlock]; 

    // set predicate (artist name) 
    NSPredicate *pred = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"name = \"%@\"", theArtist]]; 
    [fetch setPredicate:pred]; 

    [moc lock]; 
    NSArray *response = [moc executeFetchRequest:fetch error:&error]; 
    [moc unlock]; 

    if (error) 
    [NSApp presentError:error]; 

    if ([response count] == 0) // empty resultset --> no artists with this name 
    { 
    [artistObject setValue:theArtist forKey:@"name"]; 
    NSLog(@"%@ not found. Adding.", theArtist); 

    return artistObject; 
    } 
    else 
    return [response objectAtIndex:0]; 
} 

@end 
+0

不行。它仍然擊中'return artistObject';'並停下來。有趣的是,如果我點擊多次觸發此動作的按鈕,它會每次重複第一首歌曲/藝術​​家的相同動作。有沒有辦法使用調試器來找出它正在等待什麼(如果有的話)? – spamguy 2010-04-03 03:05:42

+0

不是我所知道的,但希望別人可以跳進去。 – 2010-04-05 16:10:20

0

不能鎖定NSManagedObjects!