利用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 ...
随机推荐
- SpringBoot学习笔记(8)-----SpringBoot文件上传
直接上代码,上传文件的前端页面: <body> <form action="/index/upload" enctype="multipart/form ...
- document.body
比如document.body,最好是写成document.getElementsByTagName("body")[0];
- 注解@SuppressWarnings
在JAVA中注解@SuppressWarnings("deprecation")的Deprecation是什么意思 过期的 @SuppressWarnings("depr ...
- [NOIP2003提高组]侦探推理
题目:洛谷P1039.Vijos P1106.codevs1089. 题目大意:给你一系列证词,要你求出谁是凶手.具体题目见原题. 解题思路:我们枚举犯人和星期,一个一个进行判断.如果成功则记录答案, ...
- Maven命令下载源码和javadocs
1:Maven命令下载源码和javadocs 当在IDE中使用Maven时如果想要看引用的jar包中类的源码和javadoc需要通过maven命令下载这些源码,然后再进行引入,通过mvn命令能够容易的 ...
- 队列(Queue)-c实现
相对而言,队列是比较简单的. 代码还有些warning,我改不动,要找gz帮忙. #include <stdio.h> typedef struct node { int data; st ...
- Linux gcc中的LIBRARY_PATH 和 LD_LIBRARY_PATH
1. GNU 上关于LIBRARY_PATH的说明: LIBRARY_PATH The value of LIBRARY_PATH is a colon-separated list of direc ...
- [terry笔记]redhat5.5_11gR2_RAC_安装
redhat5.5_11gR2_RAC_安装,这篇主要记录RAC安装的执行步骤,最烦琐的就是前期配置,到后面图形界面runInstaller,asmca,dbca就很容易了. --hostname检查 ...
- EEPlat PaaS中的多租户数据隔离模式
EEPlat PaaS支持三种租户的数据隔离技术:Sparce Column.tenantId字段隔离.每一个租户独立数据库. 1)Sparce Column,和Salesforce Appforce ...
- 走进windows编程的世界-----消息处理函数(2)
一 WM_PAINT消息 1 WM_PAINT的产生 因为窗体的互相覆盖等,产生须要绘制的区域,那么会产生WM_PAINT消息. 普通情况下,不直接发送WM_PAINT消息,通过API声明须要 ...