关于ios:Objective-C中的属性声明

Property declaration in Objective-C

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
How does an underscore in front of a variable in a cocoa objective-c class work?

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

那么,我们开始吧。在我们的.h文件中,我们编写了以下行:

1
@property (nonatomic) double speed;

在我们的.m文件中,我们执行以下操作:

1
@synthesize speed = _speed;

为什么?据我所知,属性生成一个实例变量,并为它创建setter和getter。但到底怎么回事

1
@synthesize speed = _speed

怎么办?正如常识告诉我的,我们把速度的值赋给速度。可以。我们在哪里宣布速度?为什么编译器不给我们一个错误?这是什么意思?为什么这么模糊的代码?

我的问题是:

如果我只是

1
@synthesize speed;

如果没有速度,我会得到错误或一些错误吗?这个语法后面的原因是什么?他们做的时候在想什么?速度从哪里来?它是什么?它是指针还是实值?怎么回事?


那么,_speed是属性使用的实例变量。如果您真的想要完整地声明它,您需要写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@interface Foo
{
    double _speed;
}

@property double speed;

@end

@implementation Foo

@synthetize speed = _speed;

@end

现在xcode 4.4被释放了,其中大部分内容是不必要的,为了保持理智,应该省略掉。

基本上,你要做的就是:

1
2
3
4
5
@interface Foo

@property double speed;

@end

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


你不必这么做。这只是惯例。…=速度将创建一个名为"速度"的属性,其setter和getter将以速度命名。让你区分

1
self.speed = value;

1
speed = value;

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

1
_speed = value;

在那种情况下是正确的。

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

如果在synthesis语句中省略"=u speed",则该属性将仅命名为"speed"。如果你不犯任何错误,那么这将是完美的工作。


好吧,你不必这么做…

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

换句话说,通过这样做:

1
@synthesize myProperty;

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

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

通过使用代码中的myProperty访问此文件,您将期望获得anotherProperty的值。

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

1
self.myProperty

因此,在目标C中,我们可以采取以下措施来避免这种情况:

1
@synthesize myProperty = _myProperty;

因此,在代码中,直接引用myProperty实际上是一个错误,而必须执行self.myProperty_myProperty访问。


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

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

  • 您需要释放释放内存,这些内存可能会被DealLoc中的属性使用。
  • 您可以使用self.field = nil,但这种方法可能会导致问题
  • 因此,您需要在这个属性后面使用一个实例变量,这样您就可以在dealoc中[_field release];它。
  • 如果需要访问初始值设定项中的属性,也可以这样做。

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

    • 绝不能不小心直接使用IVAR,破坏物业内存管理合同
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @property (retain) UILabel *label;

    ...

    @synthesize label;

    ...

    -(void)viewDidLoad {
       [super viewDidLoad];

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

    在这里不小心错过了自我。你使label成为潜在的"悬空指针"。如果使用上述代码@synthesize label = _label;,则会产生编译器错误。

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

    从文档中

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

    你不必这么做。@synthesize speed工作得很好。


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


    这是一个命名约定,你不必这么做。人们这样做是为了区分实例变量和属性。

    通常它去

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    .h

    @interface myClass : NSObject
    {
        NSNumber *_speed
    }

    @property (nonatomic, strong) NSNumber *speed;

    .m

    @implementation
    @syntesize speed = _speed;