description メソッドでは、プロパティを使用していません。ivar にアクセスしています。
-(NSString*) description
{
return [NSString stringWithFormat:@"Event< timestamp:%d, start:%d >",
timestamp,
startTime]; // <-- This is accessing the instance variable, not the property.
}
これはあなたのために働くでしょう:
-(NSString*) description
{
return [NSString stringWithFormat:@"Event< timestamp:%d, start:%d >",
timestamp,
self.startTime]; // <-- This is using the property accessor.
}
プロパティと ivar の関係は常に人々を混乱させます。:) このすべてをすでに知っている場合は、スキップしてください。
上記のようにプロパティを作成して合成すると、次の 2 つのことが起こります。
- 適切なタイプの ivar が作成されます。
- その ivar を返す getter 関数が作成されます。
ポイント 2 の重要な部分は、デフォルトで、ivar と getter 関数 (およびプロパティ) が同じ名前を持つことです。
したがって、この:
@interface Event
@property(nonatomic, assign) NSUInteger timestamp;
@property(nonatomic, readonly, getter = timestamp) NSUInteger startTime;
@end
@implementation Event
@synthesize timestamp, startTime;
@end
...これに変わります:
@interface Event {
NSUInteger timestamp;
NSUInteger startTime;
}
@end
@implementation Event
- (NSUInteger) timestamp {
return timestamp
}
- (void) setTimestamp:(NSUInteger) ts {
timestamp = ts;
}
- (NSUInteger) startTime {
return [self timestamp];
}
@end
ドット構文がどのように機能するかは、次のとおりです。
NSUInteger foo = myEvent.startTime;
本当に
NSUInteger foo = [myEvent startTime];
つまり、ivar にアクセスすると、ivar にアクセスすることになります。プロパティを使用するときは、値を返す関数を呼び出しています。さらに重要なことは、構文が非常に似ているため、あることを意図したときに別のことを行うのが非常に簡単になることです。この理由から、多くの人は日常的に ivar の先頭にアンダースコアを付けて合成し、失敗しにくくしています。
@property(nonatomic, assign) NSUInteger timestamp;
@property(nonatomic, readonly, getter = timestamp) NSUInteger startTime;
@synthesize timestamp = _timestamp;
@synthesize startTime = _startTime;
NSLog( @"startTime = %d", _startTime ); // OK, accessing the ivar.
NSLog( @"startTime = %d", self.startTime ); // OK, using the property.
NSLog( @"startTime = %d", startTime ); // NO, that'll cause a compile error, and
// you'll say "whoops", and then change it
// to one of the above, thereby avoiding
// potentially hours of head-scratching. :)