iOS知识基础篇--@property,@synthesize, nonatomic,atomic,strong,weak,copy,assign,retain详解
一、@property
这个关键词的唯一作用就是声明getter、setter方法接口。
二、@synthesize
实现setter、getter方法,找不到实例变量则主动创建一个。
三、nonatomic与atomic
atomic原子操作,提供多线程安全,setter方法会发生变化;基本来讲是防止在写未完成的时候被另外一个线程读取,造成数据错误,但是这种操作的弊端就是非常消耗内存资源,苹果手机的内存资源相当宝贵,所以没有使用多线程间的通讯编程,用nonatomic是一个不错的选择。
指出访问器不是原子操作,而默认地,访问器是原子操作。也就是说
,在多线程环境下,解析的访问器提过一个队属性的安全访问,从获取器得到的返回值或者通过设置器设置的值可以一次完成,即便是别的线程也正在对其进行方未能。如果没有指定nonatomic,在自己管理内存的环境中,解析的访问器保留并自动释放返回的值,如果指定了nonatomic,那么访问器只是简单的返回这个值。
四、assign、retain、copy,这是三个关键词得好好说一下。
如:NSString * house = [[NSString alloc] initWithFormat:@"The house is mine"];
首先在堆上分配一段内存来存储@"The house is mine", 假设内存地址为:0X000 内容则为:@"The house is mine"
然后在栈上分配一段内存存储house,假设地址为0XFFFF,内容就是0X0000。
1、assign:NSString * myHouse = [house assign];
此时house和myHouse完全相同,地址都为0XFFFF,内容为0X0000,也就是说myHouse只是house的一个别名,对任何一个操作就等于对另一个操作,因此retainCount不需要增加。
所有属性都 默认 assign ,通常用于标量(简单变量 int , float , CGRect 等)
一种典型情况是用在对对象没有所有权的时候,通常是 delegate ,避免造成死循环(如果用 retain 的话会死循环)
2、retain:NSString * myHouse = [house retain];
此时myHouse的地址不再是0XFFFF,可能是0XEEEE,但内容为0X0000,所以说house和myHouse都可以管理"The
house is mine"所在的内存,因此retainCount需要增加1,
3、copy:NSString * myHouse = [house copy];
此时会在堆上重新开辟一段内存存放@"The house is mine",假设内存地址为:0X1111,内容则为:@"The house is mine"
同时会在栈上为myHouse分配内存,假设地址为:0XBBBB,内容为:0X1111,也就是说myHouse是一个新的对象,与house没有任何关系,很明显,retainCount增加1,
属性必须是 objc 对象,拥有对象所有权,必须在 dealloc 中 release 一次。且属性必须实现 NSCopying 协议
一般常用于 NSString 类型
五、strong与weak
参考文献: iOS ARC 完全指南
提示:本文中所说的"实例变量"即是"成员变量","局部变量"即是"本地变量"
5-1、简介
ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain、release、autorelease语句。你不再需要担心内存管理,因为编译器为你处理了一切
注意:ARC 是编译器特性,而不是 iOS 运行时特性(除了weak指针系统),它也不是类似于其它语言中的垃圾收集器。因此 ARC 和手动内存管理性能是一样的,有时还能更加快速,因为编译器还可以执行某些优化
5-2、原理
ARC 的规则非常简单:只要还有一个变量指向对象,对象就会保持在内存中。当指针指向新值,或者指针不再存在时,相关联的对象就会自动释放。这条规则对于实例变量、synthesize属性、局部变量都是适用的
5-3、strong指针
控制器中有个文本输入框框属性
@property (nonatomic, assign) IBOutlet UITextField *nameField;
1.如果用户在文本框中输入mj这个字符串
那么就可以说,nameField的text属性是NSString对象的指针,也就是拥有者,该对象保存了文本输入框的内容
2.如果执行了如下代码
NSString *name = self.nameField.text;
一个对象可以有多个拥有者,在上面代码中,name变量同样也是这个NSString对象的拥有者,也就是有两个指针指向同一个对象
3.随后用户改变了输入框的内容,比如
此时nameFeild的text属性就指向了新的NSString对象。但原来的NSString对象仍然还有一个所有者(name变量),因此会继续保留在内存中
4.当name变量获得新值,或者不再存在时(如局部变量方法返回时、实例变量对象释放时),原先的NSString对象就不再拥有任何所有者,retain计数降为0,这时对象会被释放
如,给name变量赋予一个新值
name = @;
我们称name和nameField.text指针为"Strong指针",因为它们能够保持对象的生命。默认所有实例变量和局部变量都是Strong指针
5-4、weak指针
weak型的指针变量仍然可以指向一个对象,但不属于对象的拥有者
1.执行下面的代码
__weak NSString *name = self.nameField.text;
name变量和nameField.text属性都指向同一个NSString对象,但name不是拥有者
2.如果文本框的内容发生变化,则原先的NSString对象就没有拥有者,会被释放,此时name变量会自动变成nil,称为空指针
weak型的指针变量自动变为nil是非常方便的,这样阻止了weak指针继续指向已释放对象,避免了野指针的产生,不然会导致非常难于寻找的Bug,空指针消除了类似的问题
3.weak指针主要用于“父-子”关系,父亲拥有一个儿子的strong指针,因此父亲是儿子的所有者;但为了阻止所有权循环,儿子需要使用weak指针指向父亲。典型例子是delegate模式,你的ViewController通过strong指针(self.view)拥有一个UITableView, UITableView的dataSource和delegate都是weak指针,指向你的ViewController
5-5、strong和weak指针的使用注意
1.下面代码是有问题的:
__weak NSString *str = [[NSString alloc] initWithFormat:@];
"%@"
str是个weak指针,所以NSString对象没有拥有者,在创建之后就会被立即释放。Xcode还会给出警告("Warning:
Assigning retained object to weak variable; object will be released
after assignment")
2.一般的指针变量默认就是strong类型的,因此一般我们对于strong变量不加__strong修饰,以下两行代码是等价的:
NSString *name = self.nameField.text;
__strong NSString *name = self.nameField.text;
3.属性可以是strong或weak,写法如下
- weak一般应用: UI控件
- strong一般应用: OC对象类型(NSArray、NSDate、NSNumber、模型类)一个对象只要有强指针引用着,就不会被销毁
@property
@property (nonatomic, weak) id delegate;
4.以下代码在ARC之前是可能会行不通的,因为在手动内存管理中,从NSArray中移除一个对象时,这个对象会发送一条release消息,可能会被立即释放。随后NSLog()打印该对象就会导致应用崩溃
id obj = [array objectAtIndex:];
];
"%@", obj);
在ARC中这段代码是完全合法的,因为obj变量是一个strong指针,它成为了对象的拥有者,从NSArray中移除该对象也不会导致对象被释放
四.属性( @property )与成员变量的那些事 :
- 属性对成员变量扩充了存取方法 .
- 属性默认会生成带下划线的成员变量 .
- 早期的 Xcode 不支持自动合成成员变量的存取方法 , 所以古老的iOS工程师是愤怒的 .
- 后来 Xcode 智能了一点 , 可以用 @synthesize 关键字自动合成成员变量的存取方法 , 此时的iOS工程师是郁闷的 .
- 现在 Xcode 会在我们声明属性时自动合成存取方法 , 连@synthesize都不用写了 , 这样iOS工程师彻底解放了 .
- 顺便提一下 @dynamic , 这个关键字是告诉编译器存取方法在运行时会有的 . 也可以说 @dynamic 是工程师自己来实现成员变量的存取方法 , @synthesize 是让 Xcode 帮你生成存取方法 .
属性中的修饰词 - 我的理解 :
assign ( ARC/MRC )
1.这个修饰词是直接赋值的意思 , 整型/浮点型等数据类型都用这个词修饰 .
2.如果没有使用 weak strong retain copy 修饰 , 那么默认就是使用 assign 了. ( 它们之间是有你没我的关系 )
3.当然其实对象也可以用 assign 修饰 , 只是对象的计数器不会+1 . ( 与 strong 的区别 )
4.如果用来修饰对象属性 , 那么当对象被销毁后指针是不会指向 nil 的 . 所以会出现野指针错误 . ( 与weak的区别 )weak ( ARC )
1.弱指针是针对对象的修饰词 , 就是说它不能修饰基本数据类型 .
2.weak 修饰的对象计数器不会+1 , 也就是直接赋值 .
3.弱引用是为打破循环引用而生的 .
4.它最被人所喜欢的原因是 它所指向的对象如果被销毁 , 它会指向 nil . 而 nil 访问什么鬼都不会报野指针错误 .strong ( ARC )
1.直接赋值并且计数器 +1 .
2.在 ARC 里替代了 retain 的作用 .retain ( MRC )
1.release 旧对象( 旧对象计数器 -1 ) , retain 新对象( 新对象计数器 +1 ) , 然后指向新对象 .
2.在set方法里面是这样的 :if (_dog) {
[_dog release];
}
_dog = [dog retain];copy ( ARC/MRC )
1.copy 在 MRC 时是这样做的 release 旧对象( 旧对象计数器 -1 ) , copy 新对象( 新对象计数器 +1 ) , 然后指向新对象 .(新对象是指最终指向的那个对象,不管深拷贝还是浅拷贝)
1.1在set方法里面是这样的 :if (_dog) {
[_dog release];
}
_dog = [dog copy];2.copy 在 ARC 时是这么干的 copy 新对象( 新对象计数器 +1 ) , 然后指向新对象 .
2.1在set方法里面是这样的 :_dog = [dog copy];
3.使用注意 :
3.1 修饰的属性本身要不可变的 . 例如 NSMutableArray 采用 copy 修饰 , 添加元素表面上可以 一到运行就崩溃了 , 因为 copy 过后实际上成了NSArray了 . ( 队友 , 我们不吭你 )
3.2 遵守 NSCopying 协议的对象使用 .nonatomic ( ARC/MRC )
1.不对set方法加锁 .
2.性能好
3.线程不安全atomic ( ARC/MRC )
1.原子属性就是对生成的 set 方法加互斥锁 @synchronized(锁对象) .
@synchronized(self) {
_delegate = delegate;
}2.需要消耗系统资源 .
3.互斥锁是利用线程同步实现的 , 意在保证同一时间只有一个线程调用 set 方法 .
4.其实还有 get 方法 , 要是同时 set 和 get 一起调用还是会有问题的 . 所以即使用了 atomic 修饰 还是不够安全 .readonly
1.让 Xcode 只生成get方法 .
2.不想把暴露的属性被人随便替换时 , 可以使用 .readwrite
1.让 Xcode 生成get/set方法 .
2.不用 readonly 修饰时 , 默认就是 readwrite .getter/setter 的自定义方法名 .
1.一般对于 有/无 是/否 等这样的属性 , getter 方法名前面加个 is 会显得通俗易懂 .
@property (nonatomic, getter = isFinish, setter = setFinish) BOOL finish;
iOS知识基础篇--@property,@synthesize, nonatomic,atomic,strong,weak,copy,assign,retain详解的更多相关文章
- MySQL基础篇(04):存储过程和视图,用法和特性详解
本文源码:GitHub·点这里 || GitEE·点这里 一.存储过程 1.概念简介 存储程序是被存储在服务器中的组合SQL语句,经编译创建并保存在数据库中,用户可通过存储过程的名字调用执行.存储过程 ...
- iOS知识基础篇 static
static关键字的作用 一.隐藏 通过static修饰的函数或者变量,在该文件中,所有位于这条语句之后的函数都可以访问,而其他文件中的方法和函数则不行: 二.静态变量 类方法不可以访问实例变量(函 ...
- MySQL基础篇(05):逻辑架构图解和InnoDB存储引擎详解
本文源码:GitHub·点这里 || GitEE·点这里 一.MySQL逻辑架构 1.逻辑架构图 基于下面的逻辑架构图,可以大致熟悉MySQL各个架构组件之间的协同工作关系. 很经典的C/S架构风格, ...
- 关于@property()的那些属性及ARC简介【nonatomic,atomic,assign,retain,strong,weak,copy。】
@property()常用的属性有:nonatomic,atomic,assign,retain,strong,weak,copy. 其中atomic和nonatomic用来决定编译器生成的gette ...
- iOS系列 基础篇 03 探究应用生命周期
iOS系列 基础篇 03 探究应用生命周期 目录: 1. 非运行状态 - 应用启动场景 2. 点击Home键 - 应用退出场景 3. 挂起重新运行场景 4. 内存清除 - 应用终止场景 5. 结尾 本 ...
- iOS系列 基础篇 04 探究视图生命周期
iOS系列 基础篇 04 探究视图生命周期 视图是应用的一个重要的组成部份,功能的实现与其息息相关,而视图控制器控制着视图,其重要性在整个应用中不言而喻. 以视图的四种状态为基础,我们来系统了解一下视 ...
- iOS系列 基础篇 05 视图鼻祖 - UIView
iOS系列 基础篇 05 视图鼻祖 - UIView 目录: UIView“家族” 应用界面的构建层次 视图分类 最后 在Cocoa和Cocoa Touch框架中,“根”类时NSObject类.同样, ...
- iOS系列 基础篇 06 标签和按钮 (Label & Button)
iOS系列 基础篇 06 标签和按钮 (Label & Button) 目录: 标签控件 按钮控件 小结 标签和按钮是两个常用的控件,下面咱们逐一学习. 1. 标签控件 使用Single Vi ...
- iOS系列 基础篇 07 Action动作和输出口
iOS系列 基础篇 07 Action动作和输出口 目录: 1. 前言及案例说明 2. 什么是动作? 3. 什么是输出口? 4. 实战 5. 结尾 1. 前言及案例说明 上篇内容我们学习了标签和按钮 ...
随机推荐
- Toolbar 工具栏 菜单 标题栏 Menu
要使用Toolbar,要先将标题栏(ActionBar)关掉: style.xml中:<style name="MainActivityTheme" parent=" ...
- unity中Camera.ScreenToWorldPoint
Camera.ScreenToWorldPointVector3 ScreenToWorldPoint(Vector3 position); 将屏幕坐标转换为世界坐标. 如何转换?假如给定一个所谓的屏 ...
- Angular之特性模块 ( Feature Module )
项目结构 一 创建特性模块,及其包含的组件.服务. ng g module art ng g component art/music ng g component art/dance ng g ser ...
- python指针
class ListNode: def __init__(self, x): self.val = x self.next = None就两个属性 value 和 next,因为单节点默认next是没 ...
- FortiGate常用命令
1.命令结构 config Configure object. 对策略,对象等进行配置 get Get dynamic and system information. 查看相关关对 ...
- linux命令学习之:passwd
passwd命令用于设置用户的认证信息,包括用户密码.密码过期时间等.系统管理者则能用它管理系统用户的密码.只有管理者可以指定用户名称,一般用户只能变更自己的密码. 语法 passwd(选项)(参数) ...
- linux命令学习之:top
top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器. top显示系统当前的进程和其他状况,是一个动态显示过程,即可以通过用户按键来不 ...
- RSA加密遇到的一个问题
1,最近在项目里面使用了RSA加密解密的功能 出现的异常情况是加解密时对于有中文的情况会出现乱码,导致无法正常解析参数 解决方案人认为:针对中文应该 先encode ,这样能有效的避免乱码
- Android 异步加载数据 AsyncTask异步更新界面
官方文档: AsyncTask enables proper and easy use of the UI thread. This class allows to perform backg ...
- webstorm 打包angular Module build failed: Error: No PostCSS Config found
angular创建项目后,在webstorm中启动时,报出如题错误,奇怪的是我从命令行启动(ng server)是没有问题的,多方寻求无果,在网上看到过说要加一个配置文件,我不信.我觉得是我配置哪里有 ...