您的位置:首页 > 移动开发 > IOS开发

iOS中成员变量和属性区别

2017-08-01 10:59 274 查看
接触iOS的人都知道,
@property
声明的属性默认会生成一个_类型的成员变量,同时也会生成
setter/getter
方法。 

但这只是在iOS5之后,苹果推出的一个新机制。看老代码时,经常看到一个大括号里面定义了成员变量,同时用了@property声明,而且还在@implementation中使用
@synthesize
方法。 

如下:

Demo
@interface ViewController ()
{
// 1.声明成员变量
NSString *myString;
}
//2.在用@property
@property(nonatomic, copy) NSString *myString;
@end

@implementation ViewController
//3.最后在@implementation中用synthesize生成set方法
@synthesize myString;
@end
1
2
3
4
5
6
7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
13

其实,发生这种状况根本原因是苹果将默认编译器从GCC转换为LLVM(
low level virtual machine
),才不再需要为属性声明实例变量了。

在没有更改之前,属性的正常写法需要
成员变量+ @property + @synthesize 成员变量
三个步骤。 

如果我们只写
成员变量+ @property
:
@interface GBViewController :UIViewController
{
NSString *myString;
}
@property (nonatomic, strong) NSString *myString;
@end
1
2
3
4
5
6
1
2
3
4
5
6
编译时会报警告:
Autosynthesized property 'myString' will use synthesized instance variable '_myString', not existing instance variable 'myString'
1
2
3
1
2
3

但更换为LLVM之后,编译器在编译过程中发现没有新的实例变量后,就会生成一个下划线开头的实例变量。因此现在我们不必在声明一个实例变量。(
注意
:==是不必要,不是不可以==) 

当然我们也熟知,
@property
声明的属性不仅仅默认给我们生成一个_类型的成员变量,同时也会生成
setter/getter
方法。

.m
文件中,编译器也会自动的生成一个实例变量
_myString
。那么在.m文件中可以直接的使用
_myString
实例变量,也可以通过属性
self.myString
.都是一样的。

注意这里的
self.myString
其实是调用的
myString
属性的
setter/getter
方法。这与C++中点的使用是有区别的,C++中的点可以直接访问成员变量(也就是实例变量)。

例如在oc中有如下代码
@interface MyViewController :UIViewController
{
NSString *name;
}
@end
1
2
3
4
5
1
2
3
4
5

在这段代码里面只是声明了一个成员变量,并没有
setter/getter
方法。所以访问成员变量时,可以直接访问
name
,也可以像C++一样用
self->name
来访问,但绝对不能用
self.name
来访问。

扩展:很多人觉得OC中的点语法比较奇怪,实际是OC设计人员有意为之。
点表达式(.)
看起来与C语言中的结构体访问以及java语言汇总的对象访问有点类似,如果点表达式出现在等号 
 左边,调用该属性名称的
setter
方法。如果点表达式出现在
右边,调用该属性名称的
getter
方法。
OC中
点表达式(.)
其实就是调用对象的
setter
getter
方法的一种快捷方式,
self.myString
= @"张三";
实际就是
[self setmyString:@"张三"];


首先我们要明白,
@synthesize
 生成了
setter/getter
方法。 

虽然现在直接使用
@property
时,编译器会自动为你生成以下划线开头的实例变量
_myString
,不需要自己手动再去写实例变量。而且也不在.m文件中通过
@synthesize
myString;
生成
setter/getter
方法。但在看老代码的时候,我们依旧可以看到有人使用
成员变量+
@synthesize 成员变量
的形式。

那么问题来了: 

我们能否认为新编译器LLVM下的
@property
 == 老编译器GCC的 
成员变量+
@property + @synthesize 成员变量
呢?

答案是否定的。 

因为
成员变量+ @property + @synthesize 成员变量
的形式,编译器不会帮我们生成
_成员变量
,因此不会操作
_成员变量
了; 

同时
@synthesize
 还有一个作用,可以指定与属性对应的实例变量, 

例如
@synthesize myString = xxx;
 

那么
self.myString
其实是操作的实例变量xxx,而非_String了。




2
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: