Ios @property使用self在幕后实际做了什么。和自我>;和uuu下划线

Ios @property使用self在幕后实际做了什么。和自我>;和uuu下划线,ios,objective-c,properties,Ios,Objective C,Properties,我仍在努力解决@implementation部分的语法错误 因此,我想了解使用@property和不使用@property的区别 第一种情况是,是一个@interface,我在{}中声明了一些变量 //ViewController.h #import <UIKit/UIKit.h> #import "Student.h" // just class i made @interface ViewController : UIViewController { S

我仍在努力解决@implementation部分的语法错误

因此,我想了解使用@property和不使用@property的区别

第一种情况是,是一个@interface,我在{}中声明了一些变量

//ViewController.h


#import <UIKit/UIKit.h>
#import "Student.h"       // just class i made

@interface ViewController : UIViewController
{
    Student *stObj;
}

第二种情况是使用@property的@interface

@interface ViewController : UIViewController

@property Student *stObj;

@end
然后像上面一样做同样的事情

stObj = [[Student alloc]init ];        //error
//self->stObj = [[Student alloc]init];  //error
//self.stObj = [[Student alloc]init];   //no error!
//_stObj = [[Student alloc]init];       //no error!
所以,正如你所看到的,我必须假设的是那个自我。而且(下划线)起作用了,看起来很像?

问题是@property的实际作用是什么导致了不同的结果

谢谢你阅读我的问题,如果我做错了什么,请纠正我



@property
自动实现实例变量的访问器(如果未指定任何实例变量,甚至会创建实例变量)。所以
@property Student*stObj
是定义和实现
-(学生*)stObj的等效och
-(无效)设置为:(学生*)学生


stdObj=…
失败的原因是默认变量名是名为的属性,其前缀为下划线,因此
\u stdObj=…
将起作用。

不同之处在于
@property
不是实例变量;相反,它是实例变量的getter/setter

当与属性一起使用时,点语法将调用
(void)setObject:(id)object
(id)object
方法--底层实例变量的访问器/变异器。默认情况下,基础实例变量是以下划线为前缀的属性名——这就是为什么通常不需要
@synthesis stdObj=\u stdObj
,因为这是默认行为


记住这一点,如果您要声明一个简单的iVar,
self.stdObj
将是非法的,除非您为该iVar声明了一个getter/setter(或将其作为属性)
self->stdObj
直接访问iVar。

首先,让我们解释一下属性是什么:它基本上是一组方法,通常用于访问实例变量。这是一个过于简单(而且有点不正确)的解释,但它在大多数情况下都足够了

您可以使用
@synthesis
关键字定义实例变量的名称,如下所示:

@property Type foo;

...

@synthesize foo = somethingElse;
在这种情况下,编译器将生成:

  • 类型为
    type
    的名为
    somethingElse
    的实例变量
  • 读取变量的方法称为
    foo
    :它只返回变量的内容
    somethingElse
  • 一种写入变量的方法,名为
    setFoo:
    :它设置变量
    somethingElse
    的内容,并负责通知键值观察者
如果不指定
@synthesis
语句,编译器将自动生成一个以下划线作为属性名前缀的实例变量。因此,如果属性名为
foo
,则自动创建的实例变量称为
\u foo

当您这样做时:

@property Student *stObj;
(没有
@synthesis
)编译器生成:

  • 类型为
    Student*
    的实例变量
    \u stObj
  • 名为
    stObj
    的方法,用于读取变量
    \u stObj
    的内容
  • 名为
    setStObj:
    的方法,用于写入变量
    \u stObj
    的内容
接下来,访问实例变量:如果范围允许,您可以直接按名称访问它们(如
\u foo
),也可以通过
->
取消引用操作符访问它们,如
self->\u foo
。后者还允许您访问其他对象的公共实例变量,如
otherObject->\u foo
。除非你真的知道自己在做什么,否则不要这样做

最后但并非最不重要的是点符号。写入
obj.method
与写入
[obj.method]
相同,写入
obj.method=value
与写入
[obj setMethod:value]
相同。也就是说,点表示法是方法调用的较短语法。(我倾向于避免使用它,因为它也是access结构成员的表示法,但这只是我自己。)

有了这些知识,你的例子很容易解释:

在您的第一个示例中:

stObj = [[Student alloc] init]; // Access to instance variable. OK.
self->stObj = [[Student alloc]init]; // Access to instance variable. OK

// The next statement is the same as [self setStObj:[[Student alloc]init];
// But there is no method named setStObj: defined.
self.stObj = [[Student alloc]init];
// Trying to access a variable that doesn't exist. It's called stObj instead.
_stObj = [[Student alloc]init];
在第二个示例中:

// There is no variable stObj, it's called _stObj in this case.
stObj = [[Student alloc]init ]; // That's why this fails.
self->stObj = [[Student alloc]init]; // And this as well.

// The property has created the `setStObj:` method, so the next
// line succeeds.
self.stObj = [[Student alloc]init];
// The property has created the _stObj instance variable, so the
// next line succeeds.
_stObj = [[Student alloc]init];
// There is no variable stObj, it's called _stObj in this case.
stObj = [[Student alloc]init ]; // That's why this fails.
self->stObj = [[Student alloc]init]; // And this as well.

// The property has created the `setStObj:` method, so the next
// line succeeds.
self.stObj = [[Student alloc]init];
// The property has created the _stObj instance variable, so the
// next line succeeds.
_stObj = [[Student alloc]init];