2

我的UITableViewCell內容創建的一部分被一個對象(CoreData NSManagedObject)初始訪問中發生的故障所延遲。這體現在細胞首先捲入視野的小呃逆中。我決定將這些對象的訪問推送到後臺線程。訪問不同線程上的NSManagedObject的objectID?

這是我如何實現它,它工作得很好,但我們都知道我們不應該訪問另一個線程中的一個線程(主線程)的NSManagedObjectContext,但我們可以獲取對象的對象ID第二個線程,如果它最初是在第一個線程中獲取的?

獲取對象ID需要一點時間,我希望能夠將其推入背景中。

MyRecord *record = [self.frc objectAtIndexPath: indexPath]; 

// Should the following be here or can it be below in the background thread? 
// NSManagedObjectID *recordObjectID = record.objectID; 

dispatch_async(_recordViewQueue, ^(void) { 
    if ([cell.origIndexPath isEqual:indexPath]) { 

     // should the following be here or above? It works here, but am I just lucky? 
     // this call seems to take about 2/100 of a second 
     NSManagedObjectID *recordObjectID = record.objectID; 

     NSManagedObjectContext *bgndContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType]; 
     bgndContext.persistentStoreCoordinator = App.sharedApp.storeCoordinator; 
     MyRecord *newRecord = (MyRecord *) [bgndContext objectWithID:recordObjectID]; 

     [self updateCell:cell withRecord:newRecord]; 

     if ([cell.origIndexPath isEqual:indexPath]) { 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       [(UIView*) cell.recordView setNeedsDisplay]; 
      }); 
     } 
    } 
}); 

這是安全嗎?或者我必須在mainThread中獲取objectID?

回答

5

在線程之間傳遞被管理對象的objectID是安全的。在線程之間使用管理對象是不安全的。使用objectID和線程的託管對象上下文來調用existingObjectWithID:error:獲取該線程的託管對象的實例。

我會更新您的代碼如下所示:

MyRecord *record = [self.frc objectAtIndexPath: indexPath]; 

NSManagedObjectID *recordObjectID = record.objectID; 

dispatch_async(_recordViewQueue, ^(void) { 
    if ([cell.origIndexPath isEqual:indexPath]) { 

     NSManagedObjectContext *bgndContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType]; 
     bgndContext.persistentStoreCoordinator = App.sharedApp.storeCoordinator; 
     NSError * error = nil; 
     MyRecord *newRecord = (MyRecord *) [bgndContext existingObjectWithID:recordObjectID error:&error]; 
     if (newRecord) { 
      [self updateCell:cell withRecord:newRecord]; 
      if ([cell.origIndexPath isEqual:indexPath]) { 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        [(UIView*) cell.recordView setNeedsDisplay]; 
       }); 
      } 
     } 
     else { 
      NSLog(@"unable to find existing object! error: %@ (userInfo: %@)", [error localizedDescription], [error userInfo]); 
     } 
    } 
}); 
+2

我建議'existingObjectWithID:錯誤:'取代'objectWithID:','因爲objectWithID:'會返回一個對象,即使是假的對象ID 。 –

+0

同意,我剪下並粘貼原始片段。現在更新爲使用existingObjectWithID:error :. –

相關問題