Objective-C中的属性声明

时间:2012-07-12 19:35:01

标签: objective-c ios

  

可能重复:
  How does an underscore in front of a variable in a cocoa objective-c class work?

所以我发现在合成属性时你必须使用下划线,这对我来说没有任何意义。

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

@property (nonatomic) double speed;

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

@synthesize speed = _speed;

为什么呢?据我所知,property生成一个实例变量并为它创建setter和getter。 但到底是什么行

@synthesize speed = _speed 

做什么? 常识告诉我,我们将_speed中的值赋予速度。好的。 我们在哪里宣布_speed?为什么编译器没有给我们错误?它应该是什么意思?为什么这么模糊的代码?

我的问题在这里:

如果我只是

会发生什么
@synthesize speed;

没有_speed,我会得到错误或一些错误吗? 这种语法后的原因是什么?制作时他们在想什么? _speed来自哪里?它是什么?它是指针还是真正的价值?发生了什么事?

7 个答案:

答案 0 :(得分: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进行直接访问。

答案 1 :(得分:1)

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

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

换句话说,通过这样做:

@synthesize myProperty;

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

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

通过代码中的myProperty访问此内容,您可能会获得anotherProperty的价值

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

self.myProperty

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

@synthesize myProperty = _myProperty;

因此,在代码中直接引用myProperty实际上是 错误 ,而您必须执行self.myProperty(属性访问)或{{ 1}}(iVar访问)。

答案 2 :(得分:1)

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

self.speed = value;

speed = value; 

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

_speed = value; 
在这种情况下,

是正确的。

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

如果在synthesize语句中省略“= _speed”,则该属性将仅被命名为“speed”。如果你没有犯任何错误,那么这将完美无缺。

答案 3 :(得分:0)

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

通常是

.h

@interface myClass : NSObject
{
    NSNumber *_speed
}

@property (nonatomic, strong) NSNumber *speed;

.m

@implementation
@syntesize speed = _speed;

答案 4 :(得分:0)

什么都不会发生 - 只需编写@synthesize速度就可以了。使用_speed只是使底层实例变量_speed而不是速度。大多数人这样做是为了防止意外地直接进入ivar,而不是通过thr getter。

答案 5 :(得分:0)

来自the documentation

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

你没有来做这件事。 @synthesize speed工作正常。

答案 6 :(得分:0)

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

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

  1. 您需要释放dealloc
  2. 中属性可能使用的内存
  3. 您可以使用self.field = nil但这种方法may cause problems
  4. 所以你需要一个在这个属性后面使用的实例变量,这样你就可以在dealloc中[_field release];
  5. 如果您需要在初始化程序中访问您的属性,则相同。

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

    • 永远不会意外地使用ivar并破坏财产的内存管理合同

    @property (retain) UILabel *label;
    
    ...
    
    @synthesize label;
    
    ...
    
    -(void)viewDidLoad {
       [super viewDidLoad];
    
       label = [[[UILabel alloc] initWithFrame:frame] autorelease];
    }
    

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

    • 局部变量或方法参数名称通常与属性名称相同 - 如果使用下划线实例变量,则不会导致任何问题