理解属性访问概念的问题

时间:2011-08-10 12:05:57

标签: iphone objective-c ios

我最近开始开发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
}

为什么前三个输出为空?我自己的属性实现是不正确的?

3 个答案:

答案 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"