之前写过一篇利用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. 网络命令 netstat -anp

    学习源推荐:http://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316661.html#undefined 疑问:

  2. 《Unix环境高级编程》读书笔记 第5章-标准I/O流

    1. 引言 标准I/O库由ISO C标准说明,由各个操作系统实现 标准I/O库处理很多细节,如缓冲区分配.以优化的块长度执行I/O等.这些处理使用户不必担心如何使用正确的块长度,这使得它便于用于使用, ...

  3. Python3基础笔记---模块

    参考博客:Py西游攻关之模块 模块的概念: 我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式.在Python中,一个.py文件就称之为 ...

  4. WCF客户端获取服务端异常[自定义异常]

    引言 经过不断的摸索,询问/调试,终于学会了关于WCF客户端与服务端之间异常的处理机制,在此来记录自己的成果,用于记录与分享给需要的伙伴们. 首先感谢[.NET技术群]里群主[轩]的大力帮助,如有需要 ...

  5. 关于Subversion主从备份方式的调整(全量、增量脚本)更新

    本文引用于http://blog.chinaunix.net/uid-25266990-id-3369172.html 之前对Subversion服务器作了迁移,关于SVN的架构也走了调整,有单一的服 ...

  6. sort排序到底怎么排序

    sort()方法 sort() 方法在适当的位置对数组的元素进行排序,并返回数组. <!DOCTYPE html> <html> <head> <meta c ...

  7. Linux学习总结(10)——Linux查看CPU和内存使用情况

    在系统维护的过程中,随时可能有需要查看 CPU 使用率,并根据相应信息分析系统状况的需要.在 CentOS 中,可以通过 top 命令来查看 CPU 使用状况.运行 top 命令后,CPU 使用状态会 ...

  8. 兼顾php和jquery新版本的checkbox的写法

    <input type="checkbox" class="scate_item" name="scategories[]" valu ...

  9. XML快速注释

    eclipse中编辑java或C/C++,python文件时,注释的快捷键均为 "CTRL + / ",编辑xml文件时,该快捷键无效. eclipse XML 注释:CTRL + ...

  10. "pom.xml" could not be activated because it does not exist.

    "pom.xml" could not be activated because it does not exist. 在sts中使用maven build,输入package然后 ...