我正在使用从Apple的DateSectionTitles示例代码派生的代码。在我的课程Appointment
中,我与Location
有关系。此外,我生成UITableViewController使用的节标识符。
@class Location;
@interface Appointment : NSManagedObject
@property (nonatomic, retain) NSDate * begin;
@property (nonatomic, retain) NSDate * end;
@property (nonatomic, retain) Location * location;
@property (nonatomic, retain) NSString *sectionIdentifier;
@property (nonatomic, retain) NSString *primitiveSectionIdentifier;
@end
@implementation Appointment
@synthesize begin = _begin;
@dynamic end;
@dynamic location;
@dynamic primitiveSectionIdentifier;
@dynamic sectionIdentifier;
#pragma mark -
#pragma mark Transient properties
- (NSString *)sectionIdentifier {
// Create and cache the section identifier on demand.
[self willAccessValueForKey:@"sectionIdentifier"];
NSString *tmp = [self primitiveSectionIdentifier];
[self didAccessValueForKey:@"sectionIdentifier"];
if (!tmp) {
/*
Sections are organized by month and year. Create the section identifier as a string representing the number (year * 1000) + month; this way they will be correctly ordered chronologically regardless of the actual name of the month.
*/
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
fromDate:[self begin]];
tmp = [NSString stringWithFormat:@"%d", ([components year] * 10000) + [components month] * 100 + [components day]];
[self setPrimitiveSectionIdentifier:tmp];
}
return tmp;
}
#pragma mark -
#pragma mark Begin setter
- (void)setBegin:(NSDate *)begin
{
// If the time stamp changes, the section identifier become invalid.
[self willChangeValueForKey:@"begin"];
[self willChangeValueForKey:@"primitiveSectionIdentifier"];
_begin = begin;
[self setPrimitiveSectionIdentifier:nil];
[self didChangeValueForKey:@"begin"];
[self didChangeValueForKey:@"primitiveSectionIdentifier"];
}
@end
问题:更改位置后,数据会出现故障。
在修改location
之前,对象看起来像这样:
<Appointment: 0x837d570> (entity: Appointment; id: 0x837c900 <x-coredata://83B2187C-00B3-4029-B4C5-4EB69C18FC59/Appointment/p1> ; data: {
begin = "2013-07-27 16:00:00 +0000";
end = "2013-07-27 18:00:00 +0000";
location = "0x837e6c0 <x-coredata://83B2187C-00B3-4029-B4C5-4EB69C18FC59/Location/p1>";
})
更改属性location
后:
<Appointment: 0x9b7b1f0> (entity: Appointment; id: 0x9b7ab50 <x-coredata://83B2187C-00B3-4029-B4C5-4EB69C18FC59/Appointment/p1> ; data: <fault>)
如果我放弃生成部分标识符并使用@dynamic
而不是@synthesized
属性,它仍然有效。造成这种情况的原因是什么?如何克服这个问题?
答案 0 :(得分:0)
感谢 Martin R ,他指出了我正确的方向,我在代码中发现了问题。
我不知道的是Core Data自动为您生成其他原始属性:
例如,给定具有属性firstName,Core Data的实体 自动生成firstName,setFirstName:,primitiveFirstName, 和setPrimitiveFirstName:。 Core Data甚至为实体提供此功能 由NSManagedObject表示。在您时禁止编译器警告 调用这些方法,你应该使用Objective-C 2.0声明 属性功能,如“声明”中所述。
(Source)
我没有意识到这一点,这导致我以错误的方式采用示例代码。它对我有用的方式现在是:
@class Location;
@interface Appointment : NSManagedObject
@property (nonatomic, retain) NSDate * primitiveBegin;
@property (nonatomic, retain) NSDate * begin;
@property (nonatomic, retain) NSDate * end;
@property (nonatomic, retain) Location * location;
@property (nonatomic, retain) NSString *sectionIdentifier;
@property (nonatomic, retain) NSString *primitiveSectionIdentifier;
@end
@implementation Appointment
@dynamic primitiveBegin;
@dynamic begin;
@dynamic end;
@dynamic location;
@dynamic primitiveSectionIdentifier;
@dynamic sectionIdentifier;
#pragma mark -
#pragma mark Transient properties
- (NSString *)sectionIdentifier {
// Create and cache the section identifier on demand.
[self willAccessValueForKey:@"sectionIdentifier"];
NSString *tmp = [self primitiveSectionIdentifier];
[self didAccessValueForKey:@"sectionIdentifier"];
if (!tmp) {
/*
Sections are organized by month and year. Create the section identifier as a string representing the number (year * 1000) + month; this way they will be correctly ordered chronologically regardless of the actual name of the month.
*/
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)
fromDate:[self begin]];
tmp = [NSString stringWithFormat:@"%d", ([components year] * 10000) + [components month] * 100 + [components day]];
[self setPrimitiveSectionIdentifier:tmp];
}
return tmp;
}
#pragma mark -
#pragma mark Begin setter
- (void)setBegin:(NSDate *)begin
{
// If the time stamp changes, the section identifier become invalid.
[self willChangeValueForKey:@"begin"];
[self setPrimitiveBegin:begin];
[self didChangeValueForKey:@"begin"];
[self setPrimitiveSectionIdentifier:nil];
}
#pragma mark -
#pragma mark Key path dependencies
+ (NSSet *)keyPathsForValuesAffectingSectionIdentifier
{
// If the value of timeStamp changes, the section identifier may change as well.
return [NSSet setWithObject:@"begin"];
}
@end