美文网首页
NSTimer/CADisplayLink循环引用

NSTimer/CADisplayLink循环引用

作者: 五蕴盛 | 来源:发表于2021-11-16 14:05 被阅读0次

我只是想记录一下,设置不了文章仅自己可见!!!shit!

1.NSTimer/CAD 实现分类 使用block打破引用

1.1 在分类里面实现

在初始化timer/cadlink对象的时候,指定target的时候,会保留其目标对象,其实就是这个target。在分类中,定时器对象指定的target是timer/cadlink的类对象,这是个单例对象,因此计时器的是否保留他无所谓,因为类对象无需回收。

2. YYWeakProxy等

NSproxy本身是一个抽象类,他遵循NSObject协议,提供了消息转发的接口。NSProxy通常来实现消息转发和懒加载初始化资源。但,需要创建NSProxy的子类,实现init以及消息转发的相关方法,才可以用。
YYWeakProxy继承了NSProxy,定义了一个弱引用的target对象,重写消息转发,让target对象去处理接收到的消息,等于让原来ViewController对象去直接处理但这里拐了一个弯,在这个弯里用弱引用解除了timer和controller的本来的强引用。

引用链 以下用——代表强引用 ,用---代表弱应用

Controller——>NSTime/CADisplayLink——>YYWeakProxy--->Controller

代码

//  NSTimer+QSTool.h
typedef void(^QSExecuteTimerBlock) (NSTimer *timer);

@interface NSTimer (QSTool)

+ (NSTimer *)qs_scheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval executeBlock:(QSExecuteTimerBlock)block repeats:(BOOL)repeats;

@end

//  NSTimer+QSTool.m
@implementation NSTimer (QSTool)

+ (NSTimer *)qs_scheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval executeBlock:(QSExecuteTimerBlock)block repeats:(BOOL)repeats{

    NSTimer *timer = [self scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(qs_executeTimer:) userInfo:[block copy] repeats:repeats];
    return timer;
}

+ (void)qs_executeTimer:(NSTimer *)timer{

    QSExecuteTimerBlock block = timer.userInfo;
    if (block) {
        block(timer);
    }
}

@end

//  CADisplayLink+QSTool.h
@class CADisplayLink;

typedef void(^QSExecuteDisplayLinkBlock) (CADisplayLink *displayLink);

@interface CADisplayLink (QSTool)

@property (nonatomic,copy)QSExecuteDisplayLinkBlock executeBlock;

+ (CADisplayLink *)displayLinkWithExecuteBlock:(QSExecuteDisplayLinkBlock)block;

@end

//  CADisplayLink+QSTool.m
@implementation CADisplayLink (QSTool)

- (void)setExecuteBlock:(QSExecuteDisplayLinkBlock)executeBlock{

    objc_setAssociatedObject(self, @selector(executeBlock), [executeBlock copy], OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (QSExecuteDisplayLinkBlock)executeBlock{

    return objc_getAssociatedObject(self, @selector(executeBlock));
}

+ (CADisplayLink *)displayLinkWithExecuteBlock:(QSExecuteDisplayLinkBlock)block{

    CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(qs_executeDisplayLink:)];
    displayLink.executeBlock = [block copy];
    return displayLink;
}

+ (void)qs_executeDisplayLink:(CADisplayLink *)displayLink{

    if (displayLink.executeBlock) {
        displayLink.executeBlock(displayLink);
    }
}
@end

1.使用category分类

- (void)viewDidLoad {
   [super viewDidLoad];
  // ...
   __weak typeof(self) weakSelf = self;
   self.timer = [NSTimer qs_scheduledTimerWithTimeInterval:timeInterval executeBlock:^(NSTimer *timer) {
       __weak typeof(weakSelf) strongSelf = weakSelf;
       [strongSelf executeTimer:timer];
   } repeats:YES];
   [self.timer fire];
   //...
}

- (void)executeTimer:(NSTimer *)timer{
   //do something
}

- (void)dealloc{
 [self.timer invalidate];
}

2.使用yyweakproxy

- (void)viewDidLoad {
    [super viewDidLoad];
   // ...
    self.displayLink = [CADisplayLink displayLinkWithTarget:[YYWeakProxy proxyWithTarget:self] selector:@selector(executeDispalyLink:)];
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
   //...
}

- (void)executeDispalyLink:(CADisplayLink *)displayLink{
    //...
}

- (void)dealloc{
      [self.displayLink invalidate];
}

相关文章

网友评论

      本文标题:NSTimer/CADisplayLink循环引用

      本文链接:https://www.haomeiwen.com/subject/kmfhtrtx.html