Objective-C中,ARC下的 strong和weak指针原理解释
提示:本文中所说的"实例变量"即是"成员变量","局部变量"即是"本地变量"
一、简介
ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain、release、autorelease语句。你不再需要担心内存管理,因为编译器为你处理了一切。
注意:ARC 是编译器特性,而不是 iOS 运行时特性(除了weak指针系统),它也不是类似于其它语言中的垃圾收集器。因此 ARC 和手动内存管理性能是一样的,有时还能更加快速,因为编译器还可以执行某些优化
二、原理
ARC 的规则非常简单:只要还有一个变量指向对象,对象就会保持在内存中。当指针指向新值,或者指针不再存在时,相关联的对象就会自动释放。这条规则对于实例变量、synthesize属性、局部变量都是适用的
三、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 = @"Jake";
我们称name和nameField.text指针为"Strong指针",因为它们能够保持对象的生命。默认所有实例变量和局部变量都是Strong指针。
四、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.subViews)拥有一个UITableView, UITableView的dataSource和delegate都是weak指针,指向你的ViewController
五、strong和weak指针的使用注意
1.下面代码是有问题的:
__weak NSString *str = [[NSString alloc] initWithFormat:@"1234"];
NSLog(@"%@", str); // 打印出来是"(null)"
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,写法如下
@property (nonatomic, strong) NSString *name;
@property (nonatomic, weak) id delegate;
4.以下代码在ARC之前是可能会行不通的,因为在手动内存管理中,从NSArray中移除一个对象时,这个对象会发送一条release消息,可能会被立即释放。随后NSLog()打印该对象就会导致应用崩溃。(非ARC,需写作 id obj = [[array objectAtIndex:0] retain]; )
id obj = [array objectAtIndex:0]; //从数组array中取出索引为0的对象,用obj变量来接收。
[array removeObjectAtIndex:0]; //让array将索引为0的对象移除。(非ARC,加入array的对象,所有权交由数组来管理)
NSLog(@"%@", obj);
在ARC中这段代码是完全合法的,因为obj变量是一个strong指针,它成为了对象的拥有者,从NSArray中移除该对象也不会导致对象被释放。
六、ARC小结
1.有了ARC,我们的代码可以清晰很多,你不再需要考虑什么时候retain或release对象。唯一需要考虑的是对象之间的关联,也就是哪个对象拥有哪个对象?
2.ARC也有一些限制:
1> 首先ARC只能工作于Objective-C对象,如果应用使用了Core Foundation或malloc()/free(),此时还是需要你来手动管理内存
2> 此外ARC还有其它一些更为严格的语言规则,以确保ARC能够正常地工作
3.虽然ARC管理了retain和release,但并不表示你完全不需要关心内存管理的问题。因为strong指针会保持对象的生命,某些情况下你仍然需要手动设置这些指针为nil,否则可能导致应用内存不足。无论何时你创建一个新对象时,都需要考虑谁拥有该对象,以及这个对象需要存活多久
4.ARC还能很好地结合C++使用,这对游戏开发是非常有帮助的。对于iOS 4,ARC有一点点限制(不支持weak指针),但也没太大关系
七、ARC使用注意总结
1.不能直接调用dealloc方法(也不能在dealloc方法里面去调[super dealloc]方法),不能调用retain,release,autorelease,retainCount方法,包括@selector(retain)的方式也不行;
Objective-C中,ARC下的 strong和weak指针原理解释的更多相关文章
-
ARC指南1 - strong和weak指针
一.简介 ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理,因 ...
-
IOS开发中ARC下的assign和weak区别
在ARC中的assign和weak可以说非常相像,导致有很多人误以为他们是一摸一样的,在任何时候都可以划等价,但事实却不是这样. 在群里,有人问,id类型的delegate属性到底是用assign还是 ...
-
ARC - strong和weak指针
ARC指南1 - strong和weak指针 提示:本文中所说的"实例变量"即是"成员变量","局部变量"即是"本地变量&qu ...
-
ARC指南 strong和weak指针
一.简介 ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理,因为编 ...
-
(转)ARC指南 - strong、weak指针
一.简介 ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理,因为编 ...
-
Objective-C中copy 、retain以及ARC中新加入的strong、weak关键字的含义
copy: 创建一个引用计数为1的对象,然后释放旧的对象 retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的引用计数为 1 Copy其实是建立了一个相同的对象,而retain不是: ...
-
在ARC下,assign和weak的区别
用了很久,却不知道它俩究竟有什么区别,作为一个新手来说,光会用不行,还要懂得原理. 首先说说区别:weak只可以修饰对象 assign既可以修饰对象也可以修饰基本 ...
-
iOS 之 Strong与Weak,_unsafe _unretained与weak区别
1. 在ARC中 strong(强引用) 相当于retain, weak(弱引用) 相当于assign.ARC下,strong告诉编译器自动插入retain.但是在ARC下,代理协议的属性依然用ass ...
-
Objective C中的ARC的修饰符的使用---- 学习笔记九
#import <Foundation/Foundation.h> @interface Test : NSObject /** * 默认的就是__strong,这里只是做示范,实际使用时 ...
随机推荐
-
selenium page object &; Page Factory
package demo; import java.util.concurrent.TimeUnit; import org.openqa.selenium.By; import org.openqa ...
-
ABP框架理论学习之Hangfire集成
返回总目录 Hangfire是一个综合的后台工作管理者.你可以将Hangfire集成到ABP中,这样就可以不使用默认的后台工作管理者了.但你仍然可以为Hangfire使用相同的后台工作API.这样,你 ...
-
C#.NET 大型通用信息化系统集成快速开发平台 4.0 版本 - 组织机构的名称编号是否允许重复?
通常情况下,一个公司内部的部门名称,编号是不可能重复的.但是是在多公司的情况下,很可能有部门名称重复的问题存在,这时需要允许部门名称重复. 例如一个大型IT公司,在2个地区都有研发部或者客户服务部,这 ...
-
vs2010 仿XCode风格的头注释宏
Sub DocumentFileHeader() Dim star As String star = "//***************************************** ...
-
cocos 自适应屏幕分辨率
提供了三种适配策略:kResolutionNoBorder:超出屏幕的部分会被裁剪,两侧没有黑边,铺满屏幕,按图片原始比例显示,图片不变形.kResolutionShowAll:整个游戏界面是可见的, ...
-
autofac meta
http://kevincuzner.com/2014/05/19/extreme-attributed-metadata-autofac/ http://*.com/ques ...
-
crontab使用和格式
什么是crontab crontab命令常见于Unix和类Unix的操作系统之中,用于设置周期性被执行的指令.具体的用法见下图: 关于crontab的格式: crontab的格式是分为6列:f1 f2 ...
-
HBase集群安装
1.HBase的机群搭建过程(在原来的hadoop0上的HBase伪分布基础上进行搭建)1.1 集群结构,主节点(hmaster)是hadoop0,从节点(region server)是hadoop1 ...
-
IIS ApplicationPoolIdentity(配置IIS讀寫網站文件)
原创地址:http://www.cnblogs.com/jfzhu/p/4067297.html 转载请注明出处 从IIS 7.5开始,Application Pool Identity的Built- ...
-
SignalR 实时推送消息
业务场景 以前做过一个东西,就是当数据库有数据更新的时候,能够自动更新到前台,那时候signalr还没出现的时候,需要自己实现轮询读库,对于数据库和程序都是比较郁闷的事情.现在利用SignalR解决数 ...