我仍在努力解决@implementation 部分中的语法错误。
所以,我想了解使用 @property 和不使用 @property 之间的区别。
第一种情况是一个 @interface,我在 {} 中声明了一些变量。
//ViewController.h
#import <UIKit/UIKit.h>
#import "Student.h" // just class i made
@interface ViewController : UIViewController
{
Student *stObj;
}
并且,我尝试使用多个标识符(_(下划线)、self.、self->、无)来引用 stObj 指针
// ViewController.m
#import "ViewController.h"
@interface ViewController () // just leaving this code cuz i haven't study what it is :)
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
stObj = [[Student alloc]init ]; //no error
//self->stObj = [[Student alloc]init]; //no error
//self.stObj = [[Student alloc]init]; //error!
//_stObj = [[Student alloc]init]; //error!
}
第二种情况是我使用@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!
所以,正如你所看到的,我必须假设的是那个 self 。和 _(下划线)有效并且看起来很相似......?
问题是@property实际上做了什么导致了不同的结果..?
感谢您阅读我的问题,如果我做错了什么,请纠正我。
最佳答案
首先,让我们解释一下属性是什么:它基本上是一组方法,通常用于访问实例变量。这是一个过于简单(并且有点不正确)的解释,但在大多数情况下就足够了。
您可以使用@synthesize
关键字定义实例变量的名称,如下所示:
@property Type foo;
...
@synthesize foo = somethingElse;
在这种情况下,编译器将生成:
- 名为
somethingElse
且类型为Type
的实例变量。 - 读取名为
foo
的变量的方法:它仅返回变量somethingElse
的内容。 - 编写变量的方法,称为
setFoo:
:它设置变量somethingElse
的内容,并负责通知键值观察者。
如果不指定@synthesize
语句,编译器会自动生成一个实例变量,其属性名以下划线为前缀。因此,如果您的属性名为 foo
,则自动创建的实例变量称为 _foo
。
当你这样做时:
@property Student *stObj;
(没有@synthesize
)编译器生成:
Student *
类型的实例变量_stObj
。- 名为
stObj
的方法,用于读取变量_stObj
的内容。 - 名为
setStObj:
的方法,用于写入变量_stObj
的内容。
接下来,访问实例变量:如果范围允许(例如 _foo
),您可以直接通过名称访问它们,也可以通过 ->< 访问它们
取消引用运算符,如 self->_foo
中所示。后者还允许您访问其他对象的公共(public)实例变量,如 otherObject->_foo
中所示。不过,除非您真正知道自己在做什么,否则不要这样做。
最后但并非最不重要的一点是点符号。编写 obj.method
与编写 [obj method]
相同,编写 obj.method = value
与编写 [ 相同obj setMethod:值]
。也就是说,点表示法是方法调用的较短语法。 (我倾向于避免它,因为它也是访问结构成员的表示法,但这只是我的想法。)
有了这些知识,您的示例就很容易解释:
在第一个示例中:
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];
关于ios - @property 实际上在幕后做了什么……使用 self.和 self-> 和 _ 下划线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22398609/