ios - 属性(property)与成员变量(ivar)有什么区别
大家讲道理
大家讲道理 2017-04-17 11:36:36
[iOS讨论组]

最近看了很多别人写的example,一直搞不懂为什么很多人同时写属性和成员变量
如下:

@interface KKProgressToolbar : UIToolbar {
    @private

    id  __weak _actionDelegate;

    UIBarButtonItem* _stopButtonItem;
    UIActivityIndicatorView* _activityIndicator;
    UILabel* _statusLabel;
    UIProgressView* _progressBar;
}

@property (nonatomic, strong) UIBarButtonItem *stopButtonItem;
@property (nonatomic, strong) UIActivityIndicatorView *activityIndicator;
@property (nonatomic, strong) UILabel *statusLabel;
@property (nonatomic, strong) UIProgressView *progressBar;

@property (nonatomic, weak) id  actionDelegate;

一般我自己写的时候,直接写@property, 然后在m文件中,写上

@synthesize aaaaa = _aaaaa;

我刚开始学IOS,不知道这个的区别是什么,望有人不嫌弃,指点一二,在此谢过!!!

大家讲道理
大家讲道理

光阴似箭催人老,日月如移越少年。

全部回复(4)
伊谢尔伦

成员变量主要是适用于iOS5之前的开发,需要程序员手动进行内存管理。iOS5之后(包括iOS5)引入了ARC(Automatic Reference Counting)同过在property中使用strong,weak等标记自动对内存进行管理。也就是说进行iOS5及以后系统版本的开发,可以放心的使用property,而无需对其进行手动的内存管理。

大家讲道理

声明了@property@synthesize后编译器会为你的实例变量生成getter和setter,这些方法会遵循你声明的内存管理的语义,在set的时候执行对应的操作,比如retaincopy等;但它们是方法,而不是变量,所以obj.foo = @"a"其实是一个语法糖,等同于[obj setFoo:@"a"]。在过去你还需要声明对应的实例变量,并通过@synthesize foo = _foo的方式建立和它们之间的关系,但新的Clang编译器会默认帮你加入@synthesize的步骤,默认实例变量形式为property名加下划线。但是你依然可以声明实例变量,并手动建立和property的关系,尤其是实例变量的形式与默认的不同,比如:@synthesize foo = _bar

一般的情况下你应该多用@property,因为它可以进行某种程度的自动内存管理(根据你声明时的语意义),但是由于getter和setter本质上是普通的方法,所以它们可以被覆盖,可以执行除了get和set额外的操作(副作用),所以在某些情况下(比如init...和dealloc方法里)你会手动去进行赋值。

同理,由于@property声明的是方法,你可以不必有对应的实例变量,而是自行实现一个getter和setter执行自定义的操作。有时候你甚至不用去声明对应的实例变量和getter/setter,因为它们在父类已经存在,或者在运行时才存在,那么这时候你会用到@dynamic而不是@synthesize,不然编译器会报错。

关于使用实例变量还是@property,其实和用不用ARC没有太多关系。。。,它们也不是互相替代的关系

大家讲道理

这类问题,建议去看最新版的Programming iOS6等书籍,不要再过多纠结以前的代码了(比如ARC以前,LLVM编译器不自动生成成员变量定义的时代)。

黄舟

本质上来讲,属性也会帮你定义一个成员变量,并根据属性的声明自动生成getter/setter 方法,其中setter 方法根据属性(property)的属性(attribute)来提供不同的内存管理策略。

简单翻译一个SO的答案:Why would you use an ivar?,展开说一下成员变量的好处。

封装

如果成员变量是private,程序中的其它对象很难直接访问该成员变量。如果是属性,相对更容易用父类方法读写属性。

性能

成员变量地址可以根据实例的内存地址偏移寻址。而属性的读写都需要函数调用,相对更慢。

非基础类型

对于复杂的C++类型,往往设为成员变量更合适,也许这种类型不支持copy,或者完全复制很麻烦。

多线程

多线程环境下,为保证数据一致性,在需要同步执行的代码段更应该使用成员变量。如果对需要同步更新的数据用getter/setter 方法,数据更新效率低,会带来更多的获取锁请求失败。

程序正确性

成员变量可以做直观的内存管理。属性可以一层层继承,还可以复写。容易出错。

二进制文件的体积

默认用属性,会生成不必要的getter/setter 方法,程序体积会变大。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号