第四十三篇、利用NSProxy解决NSTimer内存泄漏问题
发布日期:2021-08-28 20:23:49 浏览次数:58 分类:技术文章

本文共 2062 字,大约阅读时间需要 6 分钟。

问题描述:

  用NSTimer来实现每隔一定时间执行制定的任务,例如最常见的广告轮播图。如果我们在 timerWithTimeInterval:1 target:self 中指定target为当前控制器,控制器则会被timer强引用,而控制器对timer也是强引用的。一般,我们终止定时器往往在界面销毁时,即dealloc方法中写 [_timer invalidate];。基于上面的分析,由于循环引用的存在,控制器永远也不会走dealloc方法,定时器会一直执行方法,造成内存泄露。

解决方案:

  利用消息转发来断开NSTimer对象与视图之间的引用关系。初始化NSTimer时把触发事件的target替换成一个单独的对象,然后这个对象中NSTimer的SEL方法触发时让这个方法在当前的视图self中实现。

背景知识:

  NSProxy:NSProxy 是一个抽象类,它接收到任何自己没有定义的方法他都会产生一个异常,所以一个实际的子类必须提供一个初始化方法或者创建方法,并且重载forwardInvocation:方法和methodSignatureForSelector:方法来处理自己没有实现的消息。
从类名来看是代理类,专门负责代理对象转发消息的。相比NSObject类来说NSProxy更轻量级,通过NSProxy可以帮助Objective-C间接的实现多重继承的功能。

 

代码:

#import 
@interface XZHProxy : NSProxy/** * 代理的对象 */@property (nonatomic,weak)id obj;@end

 

#import "XZHProxy.h"@implementation XZHProxy/** 这个函数让重载方有机会抛出一个函数的签名,再由后面的forwardInvocation:去执行    为给定消息提供参数类型信息 */- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{    NSMethodSignature *sig = nil;    sig = [self.obj methodSignatureForSelector:aSelector];    return sig;}/** *  NSInvocation封装了NSMethodSignature,通过invokeWithTarget方法将消息转发给其他对象.这里转发给控制器执行。 */- (void)forwardInvocation:(NSInvocation *)anInvocation{    [anInvocation invokeWithTarget:self.obj];}@end

 

#import "ViewController.h"#import "XZHProxy.h"@interface ViewController ()/** *代理 */@property (nonatomic,strong)XZHProxy *proxy;/** *  定时器 */@property (nonatomic,strong)NSTimer *timer;/** *  计数 */@property (nonatomic,assign)NSInteger count;@end@implementation ViewController- (void)viewDidLoad {    [super viewDidLoad];    // Do any additional setup after loading the view, typically from a nib.    self.proxy = [XZHProxy alloc];    //作为当前控制器的代理    self.proxy.obj = self;    //target为代理    self.timer = [NSTimer timerWithTimeInterval:1 target:self.proxy selector:@selector(timerEvent) userInfo:nil repeats:YES];    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];}- (void)timerEvent{    NSLog(@"%zd",self.count++);}- (void)dealloc{    NSLog(@"----dealloc");    //释放计时器    [self.timer invalidate];}

 

转载于:https://www.cnblogs.com/HJQ2016/p/5928801.html

转载地址:https://blog.csdn.net/weixin_33970449/article/details/94452032 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Java精选笔记_Tomcat开发Web站点
下一篇:hdu 5591 BestCoder Round #65(博弈)

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年04月22日 06时25分06秒