5

可能重复:
可可objective-c 类中变量前面的下划线如何工作?

所以我发现在合成属性时必须使用下划线,这对我来说毫无意义。

那么,让我们开始吧。在我们的 .h 文件中,我们写下这一行:

@property (nonatomic) double speed;

在我们的 .m 文件中,我们这样做:

@synthesize speed = _speed;

为什么?据我所知,属性会创建一个实例变量并为其创建 setter 和 getter。但到底是什么线

@synthesize speed = _speed 

做?正如常识告诉我的那样,我们将 _speed 中的值分配给速度。好的。我们在哪里声明了_speed?为什么编译器不给我们一个错误?它应该是什么意思?为什么会有这样一个混淆的代码?

我的问题在这里:

如果我这样做会发生什么

@synthesize speed;

没有_speed,我会得到错误或一些错误吗?这个语法之后的原因是什么?他们制作的时候在想什么?_speed 来自哪里?它是什么?它是指针还是实数值?到底是怎么回事?

4

7 回答 7

5

嗯,_speed是属性使用的实例变量。如果你真的想完全声明它,你需要写:

@interface Foo
{
    double _speed;
}

@property double speed;

@end

@implementation Foo

@synthetize speed = _speed;

@end

现在 Xcode 4.4 发布了,其中大部分内容都是不必要的,为了理智起见应该省略。

基本上,您所要做的就是:

@interface Foo

@property double speed;

@end

没有实例变量,没有@synthetize,一切仍然像以前一样工作。您可以使用self.speedself->_speed直接访问。

于 2012-07-12T19:42:18.713 回答
1

好吧,你不必这样做......

但是,这样做意味着在您的实现中您不能使用该属性的非下划线名称,因为实际上这样做您会混淆直接访问 iVar 而不是通过该属性。

换句话说,通过这样做:

@synthesize myProperty;

在您的代码中,您可以通过myProperty( iVar) 或self.myProperty(属性 - 使用访问规则 - 只读/读写、getter、setter 等)引用它,如果您使用某种规则,这当然会令人困惑:

@property(nonatomic, retain, getter = anotherProperty) NSNumber myProperty

通过myProperty在代码中访问它,您将期望获得anotherProperty

这只能通过以下方式实现:

self.myProperty

所以在 Objective-C 中我们可以做以下事情来避免这种情况:

@synthesize myProperty = _myProperty;

因此,在代码中直接引用实际上是错误myProperty的,而是必须执行self.myProperty(property access) 或_myProperty(iVar access)。

于 2012-07-12T19:41:32.663 回答
1

你不必这样做。这只是常见的做法。...=_speed 将创建一个名为 _speed 的属性,它的 setter 和 getter 将以 speed 命名。这使您可以区分

self.speed = value;

speed = value; 

因为后者会产生编译器错误。

_speed = value; 

在那种情况下是正确的。

这有助于避免与保留/释放相关的错误,因为设置器将保留对象而简单的分配者不会。(self.speed = ...将调用setter!)

如果您在综合语句中省略“=_speed”,则该属性将仅命名为“speed”。如果您没有犯任何错误,那么这将完全正常。

于 2012-07-12T19:42:18.313 回答
0

文档

@synthesize speed = _speed;将属性speed指向实例变量_speed

您不必这样@synthesize speed工作得很好。

于 2012-07-12T19:57:11.940 回答
0

在具有手动内存管理的环境中:

为什么我需要一个实例变量名?

  1. 您需要释放您的属性在 dealloc 中可能使用的内存
  2. 您可以使用self.field = nil,但这种方法可能会导致问题
  3. 所以你需要一个在这个属性后面使用的实例变量,这样你就可以[_field release];在 dealloc 中使用它。

如果您需要在初始化程序中访问您的属性,则相同。

为什么我需要在实例变量名称中使用下划线?

  • 永远不要不小心直接使用 ivar 并破坏属性的内存管理合同

@property (retain) UILabel *label;

...

@synthesize label;

...

-(void)viewDidLoad {
   [super viewDidLoad];

   label = [[[UILabel alloc] initWithFrame:frame] autorelease];
}

在这里不小心错过了自我。你做了label潜在的“悬空指针”。如果你使用@synthesize label = _label;上面的代码会产生编译错误。

  • 局部变量或方法参数名称通常与属性名称相同 - 如果您使用带下划线的实例变量,则不会导致任何问题
于 2012-07-12T20:15:37.103 回答
0

它是一个命名约定,您不必这样。人们倾向于这样做,以便他们可以区分实例变量和属性。

通常它会去

.h

@interface myClass : NSObject
{
    NSNumber *_speed
}

@property (nonatomic, strong) NSNumber *speed;

.m

@implementation
@syntesize speed = _speed;
于 2012-07-12T19:41:43.387 回答
0

不会有什么不好的事情发生——只写@synthesize 速度就可以了。使用 _speed 只会使底层实例变量 _speed 而不是 speed。大多数人这样做是为了避免意外直接访问 ivar,而不是通过 thr getter。

于 2012-07-12T19:41:54.160 回答