我在这里阅读了一些关于属性的教程,但我仍然有一些疑问要澄清,是否有区别
@interface MyClass : NSObject {
}
@property(nonatomic,retain) NSString *temp;
@end
和
@interface MyClass : NSObject {
NSString *temp;
}
@property(nonatomic,retain) NSString *temp;
@end
答案 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,但为什么不让它更容易?