0

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これの原因は何ですか?どうすればこれを克服できますか?

4

1 に答える 1

0

正しい方向を教えてくれたMartin Rに感謝します。私のコードに問題が見つかりました。

私が知らなかったのは、Core Data が追加のプリミティブプロパティを自動的に生成するという事実です。

たとえば、firstName 属性を持つエンティティを指定すると、Core Data は自動的に firstName、setFirstName:、primitiveFirstName、および setPrimitiveFirstName: を生成します。Core Data は、NSManagedObject によって表されるエンティティに対してもこれを行います。これらのメソッドを呼び出すときにコンパイラの警告を抑制するには、「宣言」で説明されているように、Objective-C 2.0 の宣言されたプロパティ機能を使用する必要があります。</p>

ソース

これを知らなかったために、コード例を間違った方法で採用することになりました。それが私のために働く方法は今です:

@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
于 2013-07-21T07:29:35.193 に答える