我最近开始开发iPhone应用程序。来自C#,Objective-C对我有一些陷阱。我不明白以下片段中发生了什么:
@interface RootViewController : UITableViewController {
NSString *simpleProperty;
NSString *propertyWithUnderscoreIvar;
}
@property (nonatomic, retain) NSString *simpleProperty;
@property (nonatomic, retain) NSString *propertyWithUnderscoreIvar;
@end
@implementation RootViewController
@synthesize simpleProperty;
@synthesize propertyWithUnderscoreIvar = _propertyWithUnderscoreIvar;
- (NSString *)simpleProperty {
return @"Simple property value";
}
- (NSString *)propertyWithUnderscoreIvar {
return @"Property with underscore value";
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog([NSString stringWithFormat:@"%i %@", 1, simpleProperty]);
// --> 1 (null)
NSLog([NSString stringWithFormat:@"%i %@", 2, propertyWithUnderscoreIvar]);
// --> 2 (null)
NSLog([NSString stringWithFormat:@"%i %@", 3, _propertyWithUnderscoreIvar]);
// --> 3 (null)
NSLog([NSString stringWithFormat:@"%i %@", 4, self.simpleProperty]);
// --> 4 Simple property value
NSLog([NSString stringWithFormat:@"%i %@", 5, self.propertyWithUnderscoreIvar]);
// --> 5 Property with underscore value
}
为什么前三个输出为空?我自己的属性实现是不正确的?
答案 0 :(得分:1)
在viewDidLoad方法中,您记录的是实例变量(ivars)的值,而不是您的属性。从上面的代码示例:
@interface RootViewController : UITableViewController {
NSString *simpleProperty;
NSString *propertyWithUnderscoreIvar;
}
这会在您的类中声明两个变量 - simpleProperty 和 propertyWithUnderscoreIvar 。另一方面,以下代码声明了属性:
@property (nonatomic, retain) NSString *simpleProperty;
@property (nonatomic, retain) NSString *propertyWithUnderscoreIvar;
这些只是声明。 Objective C有点类似于C#,因为它为您提供了为类属性生成getter和setter的简便方法。在Objective-C中,这是通过@synthesize
关键字(大致类似于C#自动属性)完成的。
@synthesize simpleProperty;
@synthesize propertyWithUnderscoreIvar = _propertyWithUnderscoreIvar;
实施文件中的@synthesize关键字为您的属性创建了getter和setter方法。你的第一个合成看起来很好,它将为'simpleProperty'创建一个getter和setter,由同名的实例变量支持。你的第二个@synthesize虽然很好。它将为'propertyWithUnderscoreIvar'创建一个getter和setter,由你从未声明的实例变量'_propertyWithUnderscoreIvar'支持。这段代码适用于现代运行时但不适用于传统运行时(请注意,即使在现代运行时,@ propertyntize也会忽略'propertyWithUnderscoreIvar'ivar)。
现在您的代码为什么打印空值,在您的日志代码中执行此操作:
NSLog([NSString stringWithFormat:@"%i %@", 1, simpleProperty]);
这是直接访问实例变量。但是此时您还没有将实例变量设置为任何值。你真正打算做的是访问该属性,如下所示:
NSLog([NSString stringWithFormat:@"%i %@", 1, [self simpleProperty]);
使用[self simpleProperty]
代替调用方法simpleProperty
并返回您的硬编码值,这就是您要做的事情。
答案 1 :(得分:0)
这些
- (NSString *)simpleProperty {
return @"Simple property value";
}
- (NSString *)propertyWithUnderscoreIvar {
return @"Property with underscore value";
}
是访问者。在
NSLog([NSString stringWithFormat:@"%i %@", 1, simpleProperty]);
您正在直接访问ivar。因此,这些ivars为null,因为您没有为它们设置任何内容。在
NSLog([NSString stringWithFormat:@"%i %@", 4, self.simpleProperty]);
您通过访问者访问ivar。因此,运行时会调用您的访问者。在我看来,当你使用@synthesize
时,你不应该编写自己的访问者。至少当你刚开始用Objective C写作时。另外你的访问者有点奇怪。
答案 2 :(得分:0)
要访问getter / setter方法,您应该使用self
或任何instance
。
NSLog([NSString stringWithFormat:@"%i %@", 1, self.simpleProperty]);
上述行将按预期打印@"Simple property value"
。