ARC 下代理产生内存泄漏的情况

         在ARC下依然会发生内存泄漏的情况,比如在使用代理的时候,A有个属性参照B,B有个属性参照A,如果将各自的对象的属性设为strong属性,因为两个对象都无法释放,就会发生内存泄漏的现象;

 比如Person类让Agent对象去查看每张票的价钱并统计还剩多少张票,而Agent 让Person对象去统计有多少人去看电影,二者相互引用对方作为自己的成员变量,就会发生内存泄漏的现象,代码如下:

Person.h

#import <Foundation/Foundation.h>
@class Agent;
@interface Person : NSObject

//Person拥有一个代理属性Agent
@property(nonatomic,strong)Agent *delegate;
-(void)buyTicket;
-(int)num;
@end
Person.m

#import "Person.h"
#import "Agent.h"
@implementation Person
-(void)buyTicket{
    //Person让代理对象_delegate去统计还剩多少张票
    int left= [_delegate leftTicketNumber];
    //Person让代理对象_delegate去查看每张票的价钱
    double price =[_delegate ticketPrice];
    NSLog(@"剩余票数是 %d 每张票的价钱是%f",left,price);
}
-(int)num{
    return 100;
}
@end
Agent.h

#import <Foundation/Foundation.h>
@class Person;
@interface Agent : NSObject
-(int)leftTicketNumber;
-(double)ticketPrice;

//agent拥有代理对象Person
@property(nonatomic,retain)Person *delegate2;
-(void)numberOfPeople;
@end
Agent.m

#import "Agent.h"
#import "Person.h"
@implementation Agent

-(int)leftTicketNumber{
    return 2;
}
-(double)ticketPrice
{
    return 1000;
}
-(void)numberOfPeople
{
    //agent让代理对象 _delegate2去计算一共有多少人
    int n =[_delegate2 num];
    NSLog(@"一共有%d个人",n);
}
@end
二者相互引用对方作为自己的代理对象

Person *person =[[Person alloc]init];
    Agent *agent =[[Agent alloc]init];
    person.delegate=agent;    
    [person buyTicket];
    
    agent.delegate2=person;
    [agent numberOfPeople];
代码执行情况:

使用系统自带的工具Instruments(Xcode—>Product—>Profile—>leaks) 里面的leaks工具查看一下有无内存泄漏:

由图可知内存放生了泄漏;工具中选择Cycle & Roots 可以根据图清楚的看到两个对象发生了循环引用:

为什么会发生内存泄漏呢?让我们看一下两个对象各自的引用计数的情况

Person *person =[[Person alloc]init];
    Agent *agent =[[Agent alloc]init];
    //使用CFGetRetainCount((__bridge CFTypeRef)(obj))方法打印对象的引用计数
    NSLog(@"%ld",CFGetRetainCount((__bridge CFTypeRef)(person)));
    NSLog(@"%ld",CFGetRetainCount((__bridge CFTypeRef)(agent)));
    person.delegate=agent;
    
    [person buyTicket];
    
    agent.delegate2=person;
    NSLog(@"=======%ld",CFGetRetainCount((__bridge CFTypeRef)(person)));
    NSLog(@"=======%ld",CFGetRetainCount((__bridge CFTypeRef)(agent)));
    [agent numberOfPeople];
代码执行情况:

所以当我们创建各自的对象的时候引用计数为1,当相互引用对方作为代理的时候引用计数为2 ,最后ARC使用autorelease 一次各自对象的引用计数又变为1 ,所以这个时候两个对象都没有释放,就发生了内存泄漏的现象;

Person *person =[[Person alloc]init]; // person引用计数为1:
    Agent *agent =[[Agent alloc]init];    //agent引用计数为1
    person.delegate=agent;   //agent retain一次:引用计数为2
    [person buyTicket];
    agent.delegate2=person;  //person retain一次:引用计数为2
    [agent numberOfPeople];
解决办法:将循环参照的两个对象的其中一个的属性设置为assign(简单赋值,不改变引用计数)

@property(nonatomic,assign)Person *delegate2;

更换之后再次使用工具进行内存泄漏检测:这个时候就不发生内存泄漏的情况了

代码打印的结果为:







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值