在您的描述方法中,您没有使用该属性,而是在访问 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.
}
property-vs-ivar 的事情总是把人们搞得一团糟,所以请原谅我在闲聊一分钟。:) 如果您已经知道所有这些,请跳过。
当您创建和合成一个属性时,就像上面所做的那样,会发生两件事:
- 一个 ivar 被创建为正确的类型。
- 创建了一个 getter 函数,该函数返回该 ivar。
关于第 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。当您使用属性时,您正在调用一个返回值的函数。更重要的是,当你想要做另一件事时,做一件事是非常容易的,因为语法非常相似。正是由于这个原因,许多人经常用前导下划线合成他们的 ivars,这样就更难搞砸了。
@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. :)