2011-11-17 76 views
0

例如加載一個實體關係的一組對象:核心數據錯誤:如何正確

我有兩個實體命名ProjectTodo如果一個項目有很多待辦事項(一對多的關係),並且每個待辦事項有一個項目(見圖)。

CoreData setup of entities

在我ViewController.h我有類似:

... 
NSArray *projectArray; 
NSArray *todosArray; 

@property (nonatomic,retain) NSArray *projectArray; 
@property (nonatomic,retain) NSArray *todosArray; 
... 

在我ViewController.m我有類似:

... 
@synthesize projectArray,todosArray; 
... 
self.projectArray = [self fetchRequestForAllProjects]; 
... 

的用戶界面,在那裏他能夠選擇所有不同的項目之間。只要用戶選擇一個項目,相關的待辦事項對象就必須被設置爲加載並呈現。

問題1:如何設定待辦事項加載到的最佳方式todosArray

我做這樣的(也是在ViewController.m):

... 
// after deselecting a project entry I reset the todosArray 
self.todosArray = nil; 
... 
//when the user selects a new project I reset the todosArray like this: 
self.todosArray = [selectedProject.todos allObjects]; 
... 

但不知何故,該應用程序中的最後一行代碼極少崩潰。我的代碼有問題嗎?

問題2:對todos Objects使用另一個獲取請求會更好嗎?

UPDATE:

我使用在ViewController.m的各種方法todosArray

(a)中獲得的對象的計數, (b)中存在的表視圖內的每個待辦事項條目行,和 (c)確定所選擇的條目待辦事項(扔行選擇)

+0

有兩件事你需要檢查以幫助你調試。首先,'selectedProject'是一個有效的對象,當你調用崩潰的行時?其次,selectedProject的'todos'屬性/關係是否返回NSSet或nil?如果返回nil,那麼當您詢問該集合的所有對象時,該應用程序將會崩潰。 – Carter

+0

我添加了這些行來檢索你所問的信息,但是因爲它沒有設法再次崩潰。正如我所說的那樣,這種情況非常罕見且難以預測。當它發生時,我會發布發生的事情.Thx –

回答

2

回答#1

當你將所有的東西都拉出到一個數組中時,最好對它們進行排序。這將讓您的用戶體驗是一致的:

NSSet *projectTodoEntities = [mySelectedProject valueForKey:@"todos"]; 
NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"myKey" ascending:YES]; 
NSArray *sortedToDos = [projectTodoEntities sortedArrayUsingDescriptors:[NSArray arrayWithObject:sorter]]; 

回答#2

沒有,這一比例僅爲訪問的關係抓取是昂貴的。取指將打到磁盤等。

+0

根據對問題 –

+0

的更改,更新了答案好,非常感謝!最後一個問題:爲什麼我不應該使用'allObjects'方法?你可以看到如上所述的錯誤嗎? –

+0

@ d.ennis因爲結果未確定。您可以使用該方法,但仍需要對其進行排序,否則用戶體驗將受到影響。如果您打算將它們放入數組中,請對數組進行排序。 –

0

答案#1。 1)。請確保selectedProject是否在其他線程上被刪除,如果它被刪除,核心數據會將此NSManagedObject標記爲無效,當您嘗試訪問此對象的屬性時,將引發NSObjectInaccessibleException。 2)。所有NSManagedObject都會關聯NSManagedObjectContext,上下文在某些線程或線程隊列上受到限制,當您在訪問處於故障狀態時的「todos」關係時,它會觸發從持久存儲中獲取,您必須確保執行線程是否對NSManagedObjectContext有效,否則你應該使用下面的代碼。

NSManagedObjectContext *context = [selectedProject managedObjectContext]; 
__weak YouControllerClass *weakSelf; 
[context performBlockAndWait:^{ 
    weakSelf.todosArray = [selectedProject.todos allObjects]; 
}]; 

答案#2:使用todos對象的其他獲取請求會更好嗎?

默認情況下,「todos」關係作爲錯誤狀態返回,當您訪問項目屬性「todos:」時,它實際上會觸發第一次從持久性存儲中獲取內容,核心數據可能稍後將這些「todos」所以你將在未來獲得快速訪問(除非你重置NSManagedObjectContext)

對於大多數情況下,像用戶檢查他的限制待辦事項列表,可以觸發另一個獲取請求,如果沒有巨大的性能是不是真正的問題在待辦事項對象中使用blob數據 對於性能嚴重的場景,例如使用核心數據將數百張照片和元數據保存爲關係,當您根據照片對象的高度,寬度或URL屬性在UIView上繪製所有這些照片時,可以考慮預取照片元以避免性能問題(io操作)。