最近在排查项目中存在的内存泄漏,今天和大家分享一个CADisplayLink造成循环引用的解决方案,造成内存循环引用的原因和NSTimer是一样的都是加入runloop后对target进行了一个强持有造成的。具体代码如下:
interface CADisplayLink (JKBasicProvider)
+ (CADisplayLink *)jk_displayLinkWithTarget:(id)target
selector:(SEL)selector;
+ (CADisplayLink *)jk_displayLinkWithTarget:(id)target
block:(void(^)(CADisplayLink *displayLink))block;
@end
@interface CADisplayLinkTarget : NSObject
@property (nonatomic, weak) id actionTarget;
@property (nonatomic, assign) SEL actionSelector;
@property (nonatomic, copy) void(^actionBlock)(CADisplayLink *displayLink);
@end
@implementation CADisplayLinkTarget
- (instancetype)initWithSelector:(SEL)actionSelector target:(id)actionTarget
{
self = [super init];
if (self) {
self.actionBlock = nil;
self.actionTarget = actionTarget;
self.actionSelector = actionSelector;
}
return self;
}
- (instancetype)initWithBlock:(void(^)(CADisplayLink *displayLink))actionBlock target:(id)actionTarget
{
self = [super init];
if (self) {
self.actionBlock = actionBlock;
self.actionTarget =actionTarget;
}
return self;
}
- (void)displayLinkAction:(CADisplayLink *)displayLink
{
if (!self.actionTarget) {
[displayLink invalidate];
displayLink = nil;
} else {
if (self.actionBlock) {
self.actionBlock(displayLink);
}else{
IMP imp = [self.actionTarget methodForSelector:self.actionSelector];
void (*func)(id, SEL,CADisplayLink *) = (void *)imp;
func(self.actionTarget, self.actionSelector,displayLink);
}
}
}
@end
@implementation CADisplayLink (JKBasicProvider)
+ (CADisplayLink *)jk_displayLinkWithTarget:(id)target
selector:(SEL)selector
{
CADisplayLinkTarget *displayLinkTarget = [[CADisplayLinkTarget alloc] initWithSelector:selector target:target];
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:displayLinkTarget selector:@selector(displayLinkAction:)];
return displayLink;
}
+ (CADisplayLink *)jk_displayLinkWithTarget:(id)target
block:(void(^)(CADisplayLink *displayLink))block
{
CADisplayLinkTarget *displayLinkTarget = [[CADisplayLinkTarget alloc] initWithBlock:block target:target];
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:displayLinkTarget selector:@selector(displayLinkAction:)];
return displayLink;
}
@end
源码已验证没问题,大家可以直接复制使用。
更多技术干货文章可以扫描下方二维码: