iOS 循环引用 委托 (实例说明)
如何避免循环引用造成的内存泄漏呢:
以delegate模式为例(viewcontroller和view之间就是代理模式,viewcontroller有view的使用权,viewcontroller同时也是view的代理(处理view中的事件)):
- UserWebService.h
- #import
- //定义一个ws完成的delegate
- @protocol WsCompleteDelegate
- @required
- -(void) finished;//需要实现的方法
- @end
- @interface UserWebService:NSObject
- {
- id delegate;//一个id类型的dategate对象
- }
- @property (assign) id delegate;
- -(id)initWithUserData:(User *)user;
- -(void)connectionDidFinishLoading:(NSURLConnection *)connection;
- @end
- UserWebService.m:
- #import
- @systhesize delegate;//同步这个delegate对象
- @implementation UserWebService
- -(void)connectionDidFinishLoading:(NSURLConnection *)connection
- {
- [delegate finished]
- }
- @end
LoginViewController.h:
- #import "UserWebService.h" //包含含有委托的头文件
- @interface LoginViewController:UIViewController
- -(void)submit;
- @end
- LoginViewController.m:
- @implementation LoginViewController
- -(void) submit
- {
- User *user = [[User alloc]init];
- [user setUserId:@"username"];
- [user setPassword:@"password"];
- ws = [[UserWebService alloc] initWithUserData:user];
- ws.delegate = self;//设置委托的收听对象
- [user release];
- [ws send];
- }
- //实现委托中的方法,
- -(void) finished
- {
- NSAttry *users = [ws users];
- }
- @end
可以看到,delegate声明为assign:
- @property (assign) id delegate;
复制代码
如果声明为retain会如何?
- LoginViewController alloc了一个UserWebService,UserWebService的代理又是LoginViewController,这样就循环引用了:
- ws = [[UserWebService alloc] initWithUserData:user]; //UserWebService对象引用计数加1
- ws.delegate = self;//LoginViewController对象引用计数加1
外部框架allocLoginViewController对象后,LoginViewController对象的引用计数为2 ,release后还是无法销毁,产生内存泄漏
所以用assign而不是retain声明属性可以避免循环引用,ARC下用弱引用也可以解决
内存检测可以用xcode继承的instrument工具,不过循环引用引起的内存泄露是检测不出来的
对象release到引用计数为0后,如果对应指针没有赋值为nil,怎出现野指针
- ClassA *a = [[ClassA alloc] init];
a = nil;//alloc的内存没有任何对象可以控制它了,引用计数永远为1,这就造成了内存泄露
简单的赋值操作并不会改变对象的引用计数:
- ClassA *a = [[ClassA alloc] init];
- ClassA *b = a;//a和b指向的对象的引用计数还是1
默认为@property为@property(atomic,assign)
nonatomic: 没有对应的atomic关键字,即使上面是这么写,但atomic叧是在你没有声明这个特性的时候系统默认,你无法主动去声明这一特性。nonatomic不支持多线程访问,atomic有同步机制,支持多线程访问,如果需要多线程访问,声明为atomic(维持默认),否则声明为nonatomic,因为nonatomic效率比atomic高得多
关于assign、retain和copy: assign是系统默认的属性特性,它几乎适用亍OC的所有变量类型。对于非对象类型的变量,assign是唯一可选的特性。但是如果你在引用计数下给一个对象类型的变量声明为assign,那么你会在编译的时候收到一条来自编译器的警告。因为assign对于在引用计数下的对象特性,叧创建了一个弱引用(也就是平时说的浅复制)。返样使用变量会很危险。当你release了前一个对象的时候,被赋值的对象指针就成了无头指针了。因此在为对象类型的变量声明属性的时候,尽量少(或者不要)使用assign。
关于assign合成的setter,看起来是这样的:
- -(void)setObjA:(ClassA *)a {
- objA = a;
- }
在深入retain之前,先把声明为retain特性的setter写出来:
- -(void)setObjA:(ClassA *)a
- {
- If(objA != a)
- {
- [objA release];
- objA = a;
- [objA retain]; //对象的retain count 加1
- }
- }
明显的,在retain的setter中,变量retain了一次,那么,即使你在程序中 self.objA = a; 只写了这么一句,objA仍然需要release,才能保证对象的retain count 是正确的。但是如果你的代码 objA = a; 叧写了这么一句,那么这里只是进行了一次浅复制,对象的retain count 并没有增加,因此这样写的话,你不需要在后面release objA。 这2句话的区别是,第一句使用了编译器生成的setter来设置objA的值,而第二句叧是一个简单的指针赋值
- NSString *str = [[NSString alloc] initwithstring @“abc”];
- str = @“abcd”;‘
- [str release];
- NSLog("%@",str);//打印出abcd
str为什么没有变成野指针呢?因为字符串常量(包括NSString和@“......”)的引用计数很大(100K+),基本上不会释放掉(由OC自己管理),所以字符串常量可以不用release
iOS 循环引用 委托 (实例说明)的更多相关文章
- iOS循环引用
iOS循环引用 当前类的闭包/Block属性,用到了当前类,就会造成循环引用 此闭包/Block应该是当前类的属性,我们经常对Block进行copy,copy到堆中,以便后用. 单方向引用是不会产生循 ...
- iOS 循环引用解决方案
一.BLOCK 循环引用 一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身.构成循环引用. // 定义 block 的时候,会对外部变量做一次 cop ...
- iOS循环引用问题
今天面试问道了循环引用,所以就看了看,原来只是知道使用了Block容易造成循环引用.今天就来简单的介绍一些循环引用. 先来简单介绍一下什么是循环引用? 循环引用可以简单的理解成:A对象引用了B对象,B ...
- iOS循环引用常见场景和解决办法
好多场景会导致循环引用,例如使用Block.线程.委托.通知.观察者都可能会导致循环引用. 1.委托 遵守一个规则,委托方持有代理方的强引用,代理方持有委托方的弱引用. 实际场景中,委托方会是一个控制 ...
- iOS 循环引用
1.循环引用一般是指:A持有B,B同时持有A,从而导致死循环无法释放对象. 2.一般循环引用出现在block和delegate中,而一般解决方法就是将self变成weakSelf(强引用变成弱引用), ...
- iOS 循环引用讲解(中)
谈到循环引用,可能是delegate为啥非得用weak修饰,可能是block为啥要被特殊对待,你也可能仅仅想到了一个weakSelf,因为它能解决99%的关于循环引用的事情.下面我以个人的理解谈谈循环 ...
- 【转】iOS学习之容易造成循环引用的三种场景
ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是——循环引用.循环引用可以简单理解为A引用了B,而B又引用了A,双方都同 ...
- 【原】iOS容易造成循环引用的三种场景,就在你我身边!
ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是——循环引用.循环引用可以简单理解为A引用了B,而B又引用了A,双方都同 ...
- iOS容易造成循环引用的三种场景
iOS容易造成循环引用的三种场景 ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是--循环引用.循环引用可以简单理解为 ...
随机推荐
- jenkins 神奇变量
Hudson自己设置的一些环境变量可用于通过Hudson来执行shell脚本.Windows批处理文件和Ant文件,他们包括 Hudson设置环境变量 当一个Hudson作业执行时,它会设置一些环境变 ...
- python的redis简单使用
安装的Python版本 3.6.1 redis安装的2.8 安装redis模块 pip install redis 简单使用 redis-test.py import redis r=redis.Re ...
- Git项目协同开发学习笔记2:项目库开发协作相关命令
之前介绍了如何用git构建项目库及其后续操作的问题,但主要还是个人的操作问题,不太涉及到项目协作方面的问题,所以来说下这块.传送门在这里(后面的可以不用看了). 1.同步 首先就式同步问题:在项目协作 ...
- mysql中json_extract函数的使用?作用是什么?
需求描述: 今天看mysql中的json数据类型,涉及到一些使用,使用到了函数json_extract来 获取json字段中某个key的值,在此记录下. 操作过程: 1.查看包含json字段的表信息 ...
- python--内置函数---13
原创博文,转载请标明出处--周学伟 http://www.cnblogs.com/zxouxuewei/ Python 内置函数 内置函数 abs() divmod() input() ...
- 5 -- Hibernate的基本用法 --4 1 创建Configuration对象
org.hibernate.cfg.Configuration实例代表了应用程序到SQL数据库的配置信息,Configuration对象提供了一个buildSessionFactory()方法,该方法 ...
- Mysql Bypass小结
总结一些Bypass的方法, 1. 绕过空格过滤,使用注释/**/来替换 绕过安全狗简单的两个方法: /*'+'*/ /**a*/ 2.使用大小写绕过某些关键字的过滤 SeLeCT * From te ...
- Memcached 运行状态
memcached-tool 命令用于查看 Memcached 运行状态,用法如下: Usage: memcached-tool <host[:port] | /path/to/socket&g ...
- QT显示中文 连接上文
1.首先是建立Linux开发环境1.1.在windowsXP下安装博创公司提供的虚拟机软件VMware Workstation,版本为VMware-workstation-full-7.0.1-227 ...
- iOS开发——iOS7(及以后版本) SDK自带二维码(含条形码)扫码、二维码生成
本文转载至 http://www.cnblogs.com/leotangcn/p/4357907.html 现在很多APP都涉及了二维码扫码功能,这个功能简单实用,很多情况下用户乐于使用,现在本文带来 ...