iOS中成员变量和属性区别
2016-10-18 00:14
288 查看
历史由来:
接触iOS的人都知道,@property声明的属性默认会生成一个_类型的成员变量,同时也会生成
setter/getter方法。
但这只是在iOS5之后,苹果推出的一个新机制。看老代码时,经常看到一个大括号里面定义了成员变量,同时用了@property声明,而且还在@implementation中使用
@synthesize方法。
如下:
Demo
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ViewController</span> ()</span> { <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1.声明成员变量</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *myString; } <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//2.在用@property</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@property</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">nonatomic</span>, copy) <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *myString; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@implementation</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ViewController</span></span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//3.最后在@implementation中用synthesize生成set方法</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@synthesize</span> myString; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>
其实,发生这种状况根本原因是苹果将默认编译器从GCC转换为LLVM(
low level virtual machine),才不再需要为属性声明实例变量了。
在没有更改之前,属性的正常写法需要
成员变量+ @property + @synthesize 成员变量三个步骤。
如果我们只写
成员变量+ @property:
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">GBViewController</span> :<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">UIViewController</span></span> { <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *myString; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@property</span> (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">nonatomic</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">strong</span>) <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *myString; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>
<code class="hljs livecodeserver has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;">编译时会报警告: Autosynthesized property <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'myString'</span> will use synthesized instance <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">variable</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'_myString'</span>, <span class="hljs-operator" style="box-sizing: border-box;">not</span> existing instance <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">variable</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'myString'</span> </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
但更换为LLVM之后,编译器在编译过程中发现没有新的实例变量后,就会生成一个下划线开头的实例变量。因此现在我们不必在声明一个实例变量。(
注意:==是不必要,不是不可以==)
当然我们也熟知,
@property声明的属性不仅仅默认给我们生成一个_类型的成员变量,同时也会生成
setter/getter方法。
在
.m文件中,编译器也会自动的生成一个实例变量
_myString。那么在.m文件中可以直接的使用
_myString实例变量,也可以通过属性
self.myString.都是一样的。
注意这里的
self.myString其实是调用的
myString属性的
setter/getter方法。这与C++中点的使用是有区别的,C++中的点可以直接访问成员变量(也就是实例变量)。
例如在oc中有如下代码
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">MyViewController</span> :<span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">UIViewController</span></span> { <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">NSString</span> *name; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">@end</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
在这段代码里面只是声明了一个成员变量,并没有
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了。
顶
0
相关文章推荐
- iOS中属性与成员变量的区别
- 【转】iOS中属性与成员变量的区别
- 关于ios成员变量和属性@property区别
- iOS中属性与成员变量的区别
- IOS开发中 类、对象、实例变量、成员变量、属性变量等区别和关系
- 【转】iOS中属性与成员变量的区别
- ios属性和成员变量写在.h文件和.m文件中 区别?
- 【转】iOS中属性与成员变量的区别
- 【转】iOS中属性与成员变量的区别
- iOS中属性与成员变量的区别
- iOS中属性与成员变量的区别
- iOS成员变量、实例变量、属性变量三者的联系与区别
- IOS中属性与成员变量的区别
- iOS中属性(@proerty)与成员变量的区别
- iOS中属性与成员变量的区别
- iOS中属性与成员变量的区别
- iOS中属性与成员变量的区别
- iOS中属性与成员变量的区别
- iOS中属性与成员变量的区别
- iOS中属性与成员变量的区别