iOS 解决CADisplayLink造成循环引用方案

最近在排查项目中存在的内存泄漏,今天和大家分享一个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

源码已验证没问题,大家可以直接复制使用。
更多技术干货文章可以扫描下方二维码:
在这里插入图片描述

发布了231 篇原创文章 · 获赞 110 · 访问量 60万+

猜你喜欢

转载自blog.csdn.net/HHL110120/article/details/102760717