我对属性和错误有一个一般性的问题。
香港专业教育学院看到了许多不同的示例来使用属性,这让我有些困惑。
方法1 仅使用没有相应ivar的属性。
@property (...) Type *name;
@synthesize name;
方法2使用属性和ivar的
@interface{
Type *ivarName;
}
@property (...) Type *name;
@synthesize name = ivarName;
方法3 忽略属性并使用ivars
@interface{
Type *ivarName;
}
ivar = ...;
我目前对大多数事情都使用方法1,它可以正常工作。但是我开始想知道我是否会在这里丢失一些东西。我已经阅读了很多有关ivars VS属性的问题,但是似乎没有一个真正关心它们如何协同工作。
在大多数示例项目中,我已经看到使用方法2。所以我的问题是:定义一个属性和一个ivar,然后将该属性分配给ivar,是否比拥有一个属性有什么好处?
解决方案是否很简单:只有通过属性,才能从“外部”设置ivar?
我读过:Must every ivar be a property?和Property vs. ivar in times of ARC,但无法得出最终结论。
最佳答案
解决方案是否很简单:只有通过属性,才能从“外部”设置ivar?
本质上是。 (默认情况下)Obj-C中的Ivar受“保护”,这意味着编译器不允许您从对象自己的代码外部访问它们。例如,给出以下类声明:
@interface Dunstable : NSObject
{
NSString * crunk;
}
@end
您可能认为您可以在创建对象后访问ivar,但是尝试会导致错误:
Dunstable * d = [[Dunstable alloc] init];
d->crunk = @"Forsooth"; // Error: "Instance variable 'crunk' is protected
这就是为什么ObjC使用访问器方法。在声明的属性出现之前,必须手动定义它们:
@implementation Dunstable
- (NSString *)crunk {
return crunk; // implicit ivar access, i.e. self->crunk
}
- (void)setCrunk: (NSString *)newCrunk {
[newCrunk retain];
[crunk release];
crunk = newCrunk;
}
@end
现在,使用
@property
和@synthesize
指令为您创建这些访问器方法(以及变量本身)。 (在ARC中,设置器中的手动内存管理当然也已过时。)可以使ivar可以从对象外部访问:
@interface Dunstable : NSObject
{
@public
NSNumber * nonce;
}
@end
Dunstable * d = [[Dunstable alloc] init];
d->nonce = [NSNumber numberWithInt:2]; // Works fine
但这不是很好的Objective-C风格。
The Objective-C Programming Language文档包含与此有关的“历史记录”:
注意:过去,该接口要求声明类的实例变量,即类的每个实例的一部分的数据结构。这些是在
@interface
声明之后和方法声明之前的括号中声明的:[...]
实例变量表示实现细节,通常不应在类本身之外访问。此外,您可以在实现块中声明它们,或使用声明的属性对其进行合成。因此,通常您不应在 public 接口中声明实例变量,因此应省略花括号。
这是一个相当大的变化(实际上,令我惊讶的是,该文档中
@interface
中不再声明ivars的语法),但这绝对是更好的选择。您应该使用声明的属性;他们做正确的事,并使您的代码更干净,更安全。关于iphone - 具有相应值的属性的概念,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9854610/