之前写过一篇利用RunTime解决由NSTimer导致的内存泄漏的文章,最近和同事讨论觉得这样写有点复杂,然后发现有NSProxy这么好用的根类根类根类,没错NSProxyNSObject一样是根类,都遵守<NSObject>协议。

实际上本篇用了消息转发的机制来避免NSTimer内存泄漏的问题,无论是NSProxyNSObject的派生类在Objective-C运行时找不到消息都会执行消息转发。所以这个解决方案用NSProxyNSObject的子类都能实现,不过NSProxy从类名来看是代理类专门负责代理对象转发消息的。相比NSObject类来说NSProxy更轻量级,通过NSProxy可以帮助Objective-C间接的实现多重继承的功能。

NSProxy

NSProxy是一个抽象类,必须继承实例化其子类才能使用。NSproxy具体使用参考官方示例,在上面示例中通过消息转发实现了同时对NSProxy发送NSMutableStringNSMutableArray类型的消息间接的实现了多重继承。

关于消息转发

当程序运行时调用一个没有实现的方法,会采用三个消息转发步骤如果这三个步骤都不能成功那么此时程序会抛出一个异常。

1.添加方法到类对象,对于实例方法调用respondsToSelector:,对于类方法调用resolveClassMethod:

+(BOOL)resolveClassMethod:(SEL)sel;
-(BOOL)respondsToSelector:(SEL)aSelector;

2.查找forwardingTargetForSelector:方法,该方法返回一个新对象,如果返回nil那么将跳转到下一步骤。

-(id)forwardingTargetForSelector:(SEL)aSelector;

3.通过methodSignatureForSelector:方法获取一个NSMethodSignature类型的对象,调用forwardInvocation:方法。改方法传入一个封装了NSMethodSignatureNSInvocation对象。然后该对象通过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内存泄漏问题的更多相关文章

  1. 第四十三篇、利用NSProxy解决NSTimer内存泄漏问题

    问题描述: 用NSTimer来实现每隔一定时间执行制定的任务,例如最常见的广告轮播图.如果我们在 timerWithTimeInterval:1 target:self 中指定target为当前控制器 ...

  2. Android性能优化之利用Rxlifecycle解决RxJava内存泄漏

    前言: 其实RxJava引起的内存泄漏是我无意中发现了,本来是想了解Retrofit与RxJava相结合中是如何通过适配器模式解决的,结果却发现了RxJava是会引起内存泄漏的,所有想着查找一下资料学 ...

  3. NSTimer内存泄漏

    用NSTimer调用 timer = [NSTimer scheduledTimerWithTimeInterval:timerInterval target:self selector:@selec ...

  4. AutoDispose代替RxLifecycle优雅的解决RxJava内存泄漏问题

    使用过Rxjava的小伙伴都知道,在使用RxJava时如果处理不当,很可能会产生内存泄漏的问题. 我们使用rxjava最大的原因是响应式编程使我们的异步操作代码变得很优雅,在Android中,也使线程 ...

  5. NSTimer内存泄漏导致控制器不调用dealloc

    创建定时器会在一定的间隔后执行某些操作,一般大家会这样创建定时器,这样创建的定时,self对定时器有个引用,定时器对self也有个引用,造成了循环引用,最终造成了内存泄漏,如果定时器在做下载的操作就会 ...

  6. 使用Xcode和Instruments调试解决iOS内存泄漏

    尽管iOS 5.0加入版本号之后ARC机制,由于相互引用关系是复杂的.内存泄漏可能仍然存在.于是,懂原理是非常重要的. 这里讲述在没有ARC的情况下,怎样使用Instruments来查找程序中的内存泄 ...

  7. 使用pidof/kill组合命令,变相解决mediaserver内存泄漏【转】

    本文转载自:https://blog.csdn.net/lj402159806/article/details/78950384 在5.1系统下mediaserver有内存泄漏的问题,原因在于使用ca ...

  8. 一步步调试解决iOS内存泄漏

      虽然iOS 5.0版本之后加入了ARC机制,由于相互引用关系比较复杂时,内存泄露还是可能存在.所以了解原理很重要. 这里讲述在没有ARC的情况下,如何使用Instruments来查找程序中的内存泄 ...

  9. 调试解决iOS内存泄漏

    这里讲述在没有ARC的情况下,如何使用Instruments来查找程序中的内存泄露,以及NSZombieEnabled设置的使用. 本文假设你已经比较熟悉Obj-C的内存管理机制. 实验的开发环境:X ...

随机推荐

  1. Caffe学习--Net分析

    Caffe_Net 1.基本数据 vector<shared_ptr<Layer<Dtype> > > layers_; // 记录每一层的layer参数 vect ...

  2. mac下maven的安装配置与使用

    转载 https://blog.csdn.net/dearKundy/article/details/80291275

  3. 优动漫PAINT基础系列之拾色器教学

    在优动漫PAINT中有类似Photoshop的拾色器功能么?在优动漫PAINT中,可以直接输入颜色数值选择颜色么?当然是可以的啦!怎么呼出拾色器界面~ 看这边... 前段时间小编有收到一些小伙伴的疑问 ...

  4. 在vue组件中style scoped中遇到的坑

    在uve组件中我们我们经常需要给style添加scoped来使得当前样式只作用于当前组件的节点.添加scoped之后,实际上vue在背后做的工作是将当前组件的节点添加一个像data-v-1233这样唯 ...

  5. 洛谷 P1967 货车运输 LCA + 最小生成树

    两点之间边权最大值的最小值一定在图的最小生成树中取到. 求出最小生成树,进行倍增即可. Code: #include<cstdio> #include<algorithm> u ...

  6. (二)React简介

    React简介 2-1: React v16 (React Fiber) React比Vue更灵活 Vue更简单 2-2 开发环境搭建 如何开始:(两种方式) 1.传统方式script标签引入.js文 ...

  7. [agc016d]xor replace

    题意: 题解: 棒棒的神仙题...这题只是D题???(myh:看题五分钟,讨论两小时) 首先这个异或和是假的,比如我现在有$a=(a_1,a_2,a_3,a_4)$,操作一下$a_2$,就变成了$a= ...

  8. Innodb中的事务隔离级别和锁的关系(转载)

    nodb中的事务隔离级别和锁的关系 原文:https://tech.meituan.com/innodb-lock.html ameng ·2014-08-20 15:50 前言: 我们都知道事务的几 ...

  9. 紫书 习题 8-25 UVa 11175 (结论证明)(配图)

    看了这篇博客https://blog.csdn.net/u013520118/article/details/48032599 但是这篇里面没有写结论的证明, 我来证明一下. 首先结论是对于E图而言, ...

  10. CSDN博客给我带来的一些诱惑和选择机会

    武汉九天鸟-p2p网贷系统开发-互联网应用软件开发 公司官网:http://jiutianniao.com  社交问答:http://ask.jiutianniao.com 最近1年多,尤其是今年5月 ...