Ios @property使用self在幕后实际做了什么。和自我>;和uuu下划线
我仍在努力解决@implementation部分的语法错误 因此,我想了解使用@property和不使用@property的区别 第一种情况是,是一个@interface,我在{}中声明了一些变量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
//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];