我是否还需要在实例变量部分声明一个属性?我有什么收获?

时间:2011-07-14 09:55:16

标签: objective-c

我在这里阅读了一些关于属性的教程,但我仍然有一些疑问要澄清,是否有区别

@interface MyClass : NSObject {    
}
@property(nonatomic,retain) NSString *temp;
@end

@interface MyClass : NSObject {
    NSString *temp;
}
@property(nonatomic,retain) NSString *temp;
@end

4 个答案:

答案 0 :(得分:0)

第一个是否有效?如果没有实例变量,则很难有一个属性来访问它。

@properties适合你,所以你可以懒惰,他们为你编写以下两种方法(如果没有设置为只读):

- (void)setYourVariable:(id)new;
- (id)yourVariable;

它还允许您使用“someClass.itsVariable;”而不是“[someClass itsVariable];”

另外,当您创建头文件时,请确保最大的变量(如指针)位于顶部,最小的位于底部,这样可以节省内存。

因此:

NSObject *someObject;
NSObject *someOtherObject;

int anInt;
short aShort;
BOOL fakeBool;

而不是:

BOOL fakeBool;
NSObject *someObject;
short aShort;
NSObject *someOtherObject;
int anInt;

这与编译器有关,您可以使用sizeof()

来检查

答案 1 :(得分:0)

不同之处在于,在第一个版本中,编译器将自动创建一个实例变量(IIRC,它将命名为_temp,但我不确定)。仅在iOS和Mac 64位上支持此功能。

在第二个示例中,您提供变量。

实际上有一种方法可以告诉编译器哪个变量用于属性,我经常使用它:

@interface MyClass : NSObject {
    NSString *temp_;
}
@property(nonatomic,retain) NSString *temp;
@end

@implementation MyClass
@synthesize temp = temp_;
@end

这样变量和属性有不同的名称,你不能混淆它们(例如忘记加self.前缀)。

次要注意事项:对于copy,通常需要使用retain代替NSString *,因为您可能会为该属性分配NSMutableString *。现在,如果您要更改可变字符串,可能会发生意外情况。

答案 2 :(得分:0)

在现代运行时(Objective-C 2.0)中,它是相同的,因为编译器将为您生成变量。见Question about @synthesize

引用Objective-C编程语言>声明的属性> Property Implementation Directives

  

访问者合成的行为存在差异   取决于运行时:

     
      
  • 对于旧版运行时,实例变量必须已在当前类的@interface块中声明。 如果是实例   存在与该属性同名的变量,如果其类型为   兼容属性的类型,它被使用 - 否则,你得到一个   编译错误

  •   
  • 对于现代运行时,根据需要合成实例变量。 如果已存在同名的实例变量,则为   使用。

  •   

答案 3 :(得分:0)

我发现的实际差异是调试器似乎没有向您显示属性的值,只是实例变量。

因此,您的第一个示例(假设您使用@synthesize指令创建getter / setter)会自动创建ivar,并且没有您可以在调试期间轻松检索的值。您最终必须发送大量NSLog条消息,而不是在单步执行代码时查看值。

顺便说一句,这似乎与这个主题有关,我通常在我的ivars前加上“iv”并在XCode首选项中更改我的颜色设置,这样我就不会确定我是在访问一个属性还是一个ivar。

示例

@interface MyClass : NSObject {
    NSString *ivName;
    NSString *ivTitle;
}
@property (nonatomic, copy) NSString *Name;
@property (nonatomic, copy) NSString *Title;
@end

现在,这需要一个小技巧(将两者结合在一起)合成属性,我将在下面显示:

@implementation MyClass
@synthesize Name = ivName;
@synthesize Title = ivTitle;

通过这种方式,我一眼就能清楚地知道到底发生了什么。是的,上下文还可以告诉您是否正在访问ivar / property,但为什么不让它更容易?