2010-01-30 51 views
3

代碼:對象具有「描述」屬性時,核心數據無法解決錯誤?

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

NSEntityDescription *entity = [NSEntityDescription entityForName:@"A" 
              inManagedObjectContext:moc]; 
[fetchRequest setEntity:entity]; 

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"id" ascending:NO]; 
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; 
[fetchRequest setSortDescriptors:sortDescriptors]; 
[sortDescriptors release]; 
[sortDescriptor release]; 

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"somePredicate", someObject]; 
[fetchRequest setPredicate:predicate]; 

frc = [[NSFetchedResultsController alloc] 
     initWithFetchRequest:fetchRequest 
     managedObjectContext:moc 
     sectionNameKeyPath:@"recency" 
     cacheName:@"frc"]; 
[fetchRequest release]; 

frc.delegate = self; 

NSError *error; 
BOOL success = [frc performFetch:&error]; 
if (!success) { 
    NSLog(@"error: %@", error); 
} 

for (A *a in [frc fetchedObjects]) {   
    [someMutableArray addObject:a.b]; 
    [someMutableArray addObject:a]; 
} 

數據模型:

A和B是實體。 A具有強制性的一對一關係B. B具有逆可選的一對多關係A.

以上英語:

初始化NSFetchedResultsController抓一些數據來驅動一個實現代碼如下。初次抓取後,將數據放在一邊進行一些處理。

現在,以後,我嘗試這樣做:

id object = [someMutableArray objectAtIndex:someIndex]; 
NSLog(@"%@", object); 

if ([object isMemberOfClass:[B class]]) { 
    someVar = object.propertyFromB; // problem 
} else if ([object isMemberOfClass:[A class]]) { 
    someVar = object.propertyFromA; 
} 

問題/問題:符合 「問題」 崩潰指示。 (編輯:下面參見分辨率,但仍然希望的解釋。)

的NSLog的呼叫以上的產率:

2010-01-30 14:47:14.433 app[22618:20b] <B: 0xf7f750> (entity: B; id: 0xf7ba70 <x-coredata://B01FEC86-14D6-4973-BFDB-EDE4AFD24FDC/B/p4> ; data: <fault>) 
2010-01-30 14:47:14.438 app[22618:20b] <A: 0xf7e360> (entity: A; id: 0xf35820 <x-coredata://B01FEC86-14D6-4973-BFDB-EDE4AFD24FDC/A/p6> ; data: { 
    prop1 = value1; 
    prop2 = value2; 
    ... etc ... 
}) 

Ie的有問題的線路,如果對象是A型的,它一直存在故障並在內存中可用,但如果是B,則是故障。

我的理解是,「問題」行應該觸發故障並從存儲中獲取數據,但這不會發生。我想了解/調試原因。我曾嘗試在此附加插入willAccessKey/didAccessKey調用。我也嘗試在提取請求上設置setRelationshipKeyPathsForPrefetching:「b」。都沒有工作。

我的假設是,由於我有點濫用NSFetchedRequestController結果,故障引擎一路上感到困惑,並且在應該的時候沒有獲取錯誤。所以我猜bruteforce的方法是創建一個新的手動抓取請求來在適當的時候抓取相關的B對象。但是有更好的方法嗎?

編輯:

問題是,對象B有一個屬性「描述」,我已經確定,但與NSObject中的內置名稱衝突。 Xcode總是給我警告,但我忽略了它們,因爲我認爲「description」內部屬性​​/方法僅用於將字符串轉儲到控制檯等,而不是內部處理。

在我製作新模型後,問題消失,將「描述」重命名爲其他內容。所有的錯誤都開始按預期工作。

雖然我不明白髮生了什麼事。核心數據是否使用對象的「描述」方法進行一些內部自省?

回答

6

Core Data Programming Guide

您正在從重寫描述-如果此方法的調試操作期間觸發一個故障時,結果可能是不可預知的,並且initWithEntity氣餒:insertIntoManagedObjectContext :.您通常不應覆蓋鍵值編碼方法,如valueForKey:和setValue:forKeyPath :.

-description是NSObject中的一個方法,它返回對象的字符串表示形式。在行NSLog(@"%@", object)中,-description用於獲取您在控制檯中看到的字符串。鍵值編碼將最終使用該方法來獲取描述屬性的屬性。這對Core Data造成了很大的困惑。

當編程指南中顯示「不鼓勵」時,編程指南就顯得很慷慨。他們真的是說「是的,它會打破你的東西。」

該鏈接還有一個很好的其他方法列表,如果你重寫它們,它們會打破你的東西。

+0

這一切都是有道理的,我通常會盡量避免重寫這種「衆所周知」的方法。我沒有意識到「描述」有多敏感。 – Jaanus 2010-01-31 06:55:05

0

您需要將描述視爲保留字。這是你遇到的問題。當您嘗試擁有名爲description的屬性時,您應該收到警告。

+0

我確實收到警告。我以爲我會忽略它,因爲當我開始創建對象時,在開始時我沒有任何問題。原來,這是一個壞主意:) – Jaanus 2010-01-31 07:51:51

+1

是的,忽略警告是一個壞主意。每個開發者都應該爭取免費構建警告!甚至可能會將「警告」設置爲錯誤。 – Hunter 2010-01-31 18:33:10

+0

對具有「描述」屬性的實體進行建模是否有最佳做法?人們傾向於稱之爲「desc」還是什麼? – Hugh 2010-07-28 12:10:44

0

對於自定義描述,歡迎您從NSObject協議覆蓋-(NSString *)debugDescription。 來自Apple的文檔:

NSObject通過調用描述方法來實現此方法。 因此,默認情況下,對象的調試描述與其描述的 相同。但是,如果要將 解耦,可以覆蓋debugDescription。

相關問題