如何避免循环引用造成的内存泄漏呢:

  以delegate模式为例(viewcontroller和view之间就是代理模式,viewcontroller有view的使用权,viewcontroller同时也是view的代理(处理view中的事件)):
  

  1. UserWebService.h
  2.   #import
  3.   //定义一个ws完成的delegate
  4.   @protocol WsCompleteDelegate
  5.   @required
  6.   -(void) finished;//需要实现的方法
  7.   @end
  8.   @interface UserWebService:NSObject
  9.   {
  10.   id delegate;//一个id类型的dategate对象
  11.   }
  12.   @property (assign) id delegate;
  13.   -(id)initWithUserData:(User *)user;
  14.   -(void)connectionDidFinishLoading:(NSURLConnection *)connection;
  15.   @end
  16.   UserWebService.m:
  17.   #import
  18.   @systhesize delegate;//同步这个delegate对象
  19.   @implementation UserWebService
  20.   -(void)connectionDidFinishLoading:(NSURLConnection *)connection
  21.   {
  22.   [delegate finished]
  23.   }
  24.   @end

  LoginViewController.h:
  

  1. #import "UserWebService.h" //包含含有委托的头文件
  2.   @interface LoginViewController:UIViewController
  3.   -(void)submit;
  4.   @end
  5.   LoginViewController.m:
  6.   @implementation LoginViewController
  7.   -(void) submit
  8.   {
  9.   User *user = [[User alloc]init];
  10.   [user setUserId:@"username"];
  11.   [user setPassword:@"password"];
  12.   ws = [[UserWebService alloc] initWithUserData:user];
  13.   ws.delegate = self;//设置委托的收听对象
  14.   [user release];
  15.   [ws send];
  16.   }
  17.   //实现委托中的方法,
  18.   -(void) finished
  19.   {
  20.   NSAttry *users = [ws users];
  21.   }
  22.   @end


  可以看到,delegate声明为assign:
  

  1. @property (assign) id delegate;

复制代码

  如果声明为retain会如何?
  

  1. LoginViewController alloc了一个UserWebService,UserWebService的代理又是LoginViewController,这样就循环引用了:
  2.   ws = [[UserWebService alloc] initWithUserData:user]; //UserWebService对象引用计数加1
  3.   ws.delegate = self;//LoginViewController对象引用计数加1

  外部框架allocLoginViewController对象后,LoginViewController对象的引用计数为2 ,release后还是无法销毁,产生内存泄漏

  所以用assign而不是retain声明属性可以避免循环引用,ARC下用弱引用也可以解决

  内存检测可以用xcode继承的instrument工具,不过循环引用引起的内存泄露是检测不出来的

  对象release到引用计数为0后,如果对应指针没有赋值为nil,怎出现野指针
  

  1. ClassA *a = [[ClassA alloc] init];

  a = nil;//alloc的内存没有任何对象可以控制它了,引用计数永远为1,这就造成了内存泄露

  简单的赋值操作并不会改变对象的引用计数:
  

  1. ClassA *a = [[ClassA alloc] init];
  2.   ClassA *b = a;//a和b指向的对象的引用计数还是1

  @property:

  默认为@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,看起来是这样的:
  

  1. -(void)setObjA:(ClassA *)a {
  2.   objA = a;
  3.   }


  在深入retain之前,先把声明为retain特性的setter写出来:
  

  1. -(void)setObjA:(ClassA *)a
  2.   {
  3.   If(objA != a)
  4.   {
  5.   [objA release];
  6.   objA = a;
  7.   [objA retain]; //对象的retain count 加1
  8.   }
  9.   }


  明显的,在retain的setter中,变量retain了一次,那么,即使你在程序中 self.objA = a; 只写了这么一句,objA仍然需要release,才能保证对象的retain count 是正确的。但是如果你的代码 objA = a; 叧写了这么一句,那么这里只是进行了一次浅复制,对象的retain count 并没有增加,因此这样写的话,你不需要在后面release objA。 这2句话的区别是,第一句使用了编译器生成的setter来设置objA的值,而第二句叧是一个简单的指针赋值
  

  1. NSString *str = [[NSString alloc] initwithstring @“abc”];
  2.   str = @“abcd”;‘
  3.   [str release];
  4.   NSLog("%@",str);//打印出abcd


  str为什么没有变成野指针呢?因为字符串常量(包括NSString和@“......”)的引用计数很大(100K+),基本上不会释放掉(由OC自己管理),所以字符串常量可以不用release

转载于:https://www.cnblogs.com/DamonTang/p/3380193.html

iOS 循环引用 委托 (实例说明)相关推荐

  1. iOS循环引用问题集合、内存泄漏、僵尸对象、代码静态分析

    内存泄漏:https://my.oschina.net/llfk/blog/1031291 内存泄漏监测自动化:http://www.cocoachina.com/articles/18490 fac ...

  2. iOS容易造成循环引用的三种场景,就在你我身边!

    ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是--循环引用.循环引用可以简单理解为A引用了B,而B又引用了A,双方都同 ...

  3. [iOS]ARC下循环引用的问题

    转载自:http://blog.cnbang.net/tech/2085/ [iOS]ARC下循环引用的问题 2013-8-30 最初 最近在开发应用时碰到使用ASIHttpRequest后在某些机器 ...

  4. [iOS]-NSTimer与循环引用的理解

    目录: 参考的博客: 问题引入 循环引用 简单的循环引用 Block中的循环引用强弱共舞 Delegate中的循环引用 NSTimer 创建NSTimer 销毁NSTimer invalidate f ...

  5. iOS: NSTimer的循环引用(解决)

    首先有两个概念写在最前: 内存泄漏:系统分配的内存空间在使用完毕之后没有进行及时的回收,称之为发生了内存泄漏. 内存溢出:指在申请内存的时候,没有足够的内存空间可以使用,包括栈溢出和堆溢出. 下面开始 ...

  6. iOS开发笔记(二):block循环引用

    写这篇文章的缘由是第一次面试时被问到了block循环引用的问题,当时回答的不是很好,首先要明确的是,block是否用copy修饰决定不了循环引用的产生,在此再一次进行补强,有不对的地方还请多多指教. ...

  7. ios开发 循环引用 检测_iOS开发——Block引起循环引用的解决方案

    [目前总结了一下,在iOS平台容易引起循环引用的几个场景:一.parent-child模式二.block(编译器会提示警告)三.NSTimer] up vote 0 down vote favorit ...

  8. IOS小知识点5之内存警告、循环引用、交叉引用

    IOS的内存使用有以下几个等级,最常见的就是OSMemoryNotificationLevelWarning  OSMemoryNotificationLevelUrgent typedef enum ...

  9. ios Block底层详解、框架结构:捕获、对象类型、__block、__forwarding、循环引用

    1:捕获 2:block类型 2.1:问题 :mrc环境下  下面讲的都是mrc环境下,会真实很多 2.2:在arc下,block 自动加上copy的情况---:返回block. 2.3:在arc下, ...

最新文章

  1. 婚纱摄影小程序能带来订单吗?小程序如何做营销?
  2. 数据传输流程和socket简单操作
  3. java数组去重_再谈JavaScript数组去重
  4. java.net.URISyntaxException: Illegal character in query
  5. RedisTemplate和StringRedisTemplate使用
  6. android 属性动画还原,属性动画和补间动画
  7. Inno Setup使用技巧
  8. linux虚拟arm环境环境,Ubuntu 模拟ARM开发环境
  9. 为什么越来越多的人都不喜欢用信用卡?
  10. java房屋出租系统
  11. 现有开发语言以及适用范围
  12. mysql 按照条件计数_Mysql按条件计数的几种方法
  13. 股票涨跌的心理学原理: 过度反应理论
  14. 自制PMW3901光流模块
  15. pollard_rho
  16. 二分类神经网络结果准确率50%,loss一直在0.69的解决方法
  17. sourceinsight 查看源码的利器
  18. 「Python数据分析系列」10.使用数据
  19. 我使用Feign上传文件踩的坑,MultipartFile文件死活传不过去
  20. Destoon7.0会员中心模板 B2B系统商务中心模板源码下载

热门文章

  1. 原python实现素数判断_Python实现求最大公约数及判断素数的方法
  2. 关于数据分析部门组织架构的探讨
  3. c语言运行程序没有,这个程序怎么运行?为什么显示没有exe??
  4. python自定义函数的关键字_python学习之--自定义函数:
  5. Android NDK开发之 NDK 局部 全局引用
  6. excel函数手册_一个函数高手的成长之路
  7. Synopsys MetaWare for Linux 安装与编译指南
  8. CSS3 3D切割轮播图
  9. Kickstarter 开源其 Android 和 iOS 应用
  10. 超酷的 mip-infinitescroll 无限滚动(无限下拉)