利用NSProxy解决NSTimer内存泄漏问题
之前写过一篇利用RunTime解决由NSTimer导致的内存泄漏的文章,最近和同事讨论觉得这样写有点复杂,然后发现有NSProxy这么好用的根类,根类,根类,没错NSProxy与NSObject一样是根类,都遵守<NSObject>协议。
实际上本篇用了消息转发的机制来避免NSTimer内存泄漏的问题,无论是NSProxy与NSObject的派生类在Objective-C运行时找不到消息都会执行消息转发。所以这个解决方案用NSProxy与NSObject的子类都能实现,不过NSProxy从类名来看是代理类专门负责代理对象转发消息的。相比NSObject类来说NSProxy更轻量级,通过NSProxy可以帮助Objective-C间接的实现多重继承的功能。
NSProxy
NSProxy是一个抽象类,必须继承实例化其子类才能使用。NSproxy具体使用参考官方示例,在上面示例中通过消息转发实现了同时对NSProxy发送NSMutableString和NSMutableArray类型的消息间接的实现了多重继承。
关于消息转发
当程序运行时调用一个没有实现的方法,会采用三个消息转发步骤如果这三个步骤都不能成功那么此时程序会抛出一个异常。
1.添加方法到类对象,对于实例方法调用respondsToSelector:,对于类方法调用resolveClassMethod:。
+(BOOL)resolveClassMethod:(SEL)sel;
-(BOOL)respondsToSelector:(SEL)aSelector;
2.查找forwardingTargetForSelector:方法,该方法返回一个新对象,如果返回nil那么将跳转到下一步骤。
-(id)forwardingTargetForSelector:(SEL)aSelector;
3.通过methodSignatureForSelector:方法获取一个NSMethodSignature类型的对象,调用forwardInvocation:方法。改方法传入一个封装了NSMethodSignature的NSInvocation对象。然后该对象通过invakeWithTarget:方法将消息转发给其它对象。
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
- (void)forwardInvocation:(NSInvocation *)invocation;
使用NSProxy解决NSTimer内存泄漏
.h文件
#import <UIKit/UIKit.h>
@interface LSYViewController : UIViewController
@end
@interface LSYProxy : NSProxy
@property (nonatomic,weak) id obj;
@end
.m文件
#import "LSYViewController.h"
@interface LSYViewController ()
@property (nonatomic,strong) LSYProxy *proxy;
@property (nonatomic,strong) NSTimer *timer;
@property (nonatomic) NSInteger count;
@end
@implementation LSYViewController
-(void)viewDidLoad
{
[super viewDidLoad];
self.proxy = [LSYProxy alloc];
self.proxy.obj = self;
_timer = [NSTimer timerWithTimeInterval:1 target:self.proxy selector:@selector(timerEvent) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
}
-(void)timerEvent
{
NSLog(@"count---%d",(int)++_count);
}
-(void)dealloc
{
NSLog(@"---dealloc----");
[_timer invalidate];
}
@end
#pragma mark - LSYProxy Implementation
@implementation LSYProxy
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
NSMethodSignature *sig;
sig = [self.obj methodSignatureForSelector:aSelector];
return sig;
}
- (void)forwardInvocation:(NSInvocation *)invocation {
[invocation invokeWithTarget:self.obj];
}
@end
原理和我之前写的利用RunTime解决由NSTimer导致的内存泄漏是一样的,只不过实现不同,之前是利用关联对象的方法来断开NSTimer与视图之间的引用关系,这个是利用消息转发来断开NSTimer对象与视图之间的引用关系。
利用NSProxy解决NSTimer内存泄漏问题的更多相关文章
- 第四十三篇、利用NSProxy解决NSTimer内存泄漏问题
问题描述: 用NSTimer来实现每隔一定时间执行制定的任务,例如最常见的广告轮播图.如果我们在 timerWithTimeInterval:1 target:self 中指定target为当前控制器 ...
- Android性能优化之利用Rxlifecycle解决RxJava内存泄漏
前言: 其实RxJava引起的内存泄漏是我无意中发现了,本来是想了解Retrofit与RxJava相结合中是如何通过适配器模式解决的,结果却发现了RxJava是会引起内存泄漏的,所有想着查找一下资料学 ...
- NSTimer内存泄漏
用NSTimer调用 timer = [NSTimer scheduledTimerWithTimeInterval:timerInterval target:self selector:@selec ...
- AutoDispose代替RxLifecycle优雅的解决RxJava内存泄漏问题
使用过Rxjava的小伙伴都知道,在使用RxJava时如果处理不当,很可能会产生内存泄漏的问题. 我们使用rxjava最大的原因是响应式编程使我们的异步操作代码变得很优雅,在Android中,也使线程 ...
- NSTimer内存泄漏导致控制器不调用dealloc
创建定时器会在一定的间隔后执行某些操作,一般大家会这样创建定时器,这样创建的定时,self对定时器有个引用,定时器对self也有个引用,造成了循环引用,最终造成了内存泄漏,如果定时器在做下载的操作就会 ...
- 使用Xcode和Instruments调试解决iOS内存泄漏
尽管iOS 5.0加入版本号之后ARC机制,由于相互引用关系是复杂的.内存泄漏可能仍然存在.于是,懂原理是非常重要的. 这里讲述在没有ARC的情况下,怎样使用Instruments来查找程序中的内存泄 ...
- 使用pidof/kill组合命令,变相解决mediaserver内存泄漏【转】
本文转载自:https://blog.csdn.net/lj402159806/article/details/78950384 在5.1系统下mediaserver有内存泄漏的问题,原因在于使用ca ...
- 一步步调试解决iOS内存泄漏
虽然iOS 5.0版本之后加入了ARC机制,由于相互引用关系比较复杂时,内存泄露还是可能存在.所以了解原理很重要. 这里讲述在没有ARC的情况下,如何使用Instruments来查找程序中的内存泄 ...
- 调试解决iOS内存泄漏
这里讲述在没有ARC的情况下,如何使用Instruments来查找程序中的内存泄露,以及NSZombieEnabled设置的使用. 本文假设你已经比较熟悉Obj-C的内存管理机制. 实验的开发环境:X ...
随机推荐
- Linux 安装软件的几种方式
目录 几种安装方式 源代码编译安装 借助软件包管理器安装 二进制格式安装 总结 参考 几种安装方式 源代码编译安装 源代码包的安装一般为下载软件源代码,然后编译安装.常见的 C 程序软件的安装步骤是 ...
- python3 之 Ellipsis
在翻django 代码的时候无意中看到的, 主要还是在注解时候使用 官方参考:https://docs.python.org/3/library/constants.html#Ellipsis 注意: ...
- How Javascript works (Javascript工作原理) (二) 引擎,运行时,如何在 V8 引擎中书写最优代码的 5 条小技巧
个人总结: 一个Javascript引擎由一个标准解释程序,或者即时编译器来实现. 解释器(Interpreter): 解释一行,执行一行. 编译器(Compiler): 全部编译成机器码,统一执行. ...
- luogu P3674 小清新人渣的本愿(莫队+bitset)
这题是莫队维护bitset. 然而我并不会bitset以前讲过认为不考就没学 我真的太菜了. 首先维护一个权值的bitset--s. 操作3比较简单,我们可以\(\sqrt{x}\)枚举约数然后判断就 ...
- [Vijos P2000]A x B Problem
题目大意:叫你求A × B. 解题思路:高精度.你可千万别小看这道题,这是2017年7月27日的信息. 不过也不要怕,根据twd2的题解里写的,用普通的高精度加上一些小小的修改是可以过的. 那么直接上 ...
- linux在线添加硬盘、扫盘
1:查看scsi 硬盘设备[root@web02 ~]# ls /sys/class/scsi_host host0 host1 host2 2:检查本机现有硬盘 [root@web02 ~]# fd ...
- centeros 7开机自动挂载磁盘
场景: 使用mount命令将新发现的磁盘/dev/sdb挂载给/liu后,但是重启后又看不到磁盘? 问题导致原因: 虽然我们可以使用mount命令去挂载磁盘,但是此操作只对服务器运行期间有效,也就是临 ...
- vue-cli解析
前言 这段时间,算是空出手来写几篇文章了.由于很久都没有时间整理现在所用的东西了,所以,接下来会慢慢整理出一些文档来记录前段时间的工作和生活. 这篇文章的主题是vue-cli的理解.或许,很多人在开发 ...
- 如何查询mysql中是否表被锁
可直接在mysql命令行执行:show engine innodb status\G;(只能通过cmd或者shell登录mysql) 查看造成死锁的sql语句,分析索引情况,然后优化sql然后show ...
- zookeeper应用场景练习(分布式锁)
在寻常的高并发的程序中.为了保证数据的一致性.因此都会用到锁.来对当前的线程进行锁定.在单机操作中.非常好做到,比方能够採用Synchronized.Lock或者其它的读写多来锁定当前的线程.可是在分 ...