我对属性和错误有一个一般性的问题。

香港专业教育学院看到了许多不同的示例来使用属性,这让我有些困惑。

方法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/

10-12 00:09
查看更多