iOS 使用NSProxy来避免循环引用,用在NSTimer或者CADisplayLink中。

直接上代码:

TKSDKWeakProxy
//
//  TKSDKWeakProxy.h
//  TKSDKUniversal
//
//  Created by PC on 2021/12/22.
//  Copyright © 2021 lt. All rights reserved.
//
#import 


/**
 功能:利用NSProxy的消息转发机制来避免循环引用,用在NSTimer或者CADisplayLink中
 */

NS_ASSUME_NONNULL_BEGIN

@interface TKSDKWeakProxy : NSProxy
+ (instancetype)proxyWithTarget:(id)target;
- (instancetype)initWithTarget:(id)target;
@end

NS_ASSUME_NONNULL_END

//
//  TKSDKWeakProxy.m
//  TKSDKUniversal
//
//  Created by PC on 2021/12/22.
//  Copyright © 2021 lt. All rights reserved.
//

#import "TKSDKWeakProxy.h"

@interface TKSDKWeakProxy ()
@property (weak,nonatomic,readonly)id target;
@end

@implementation TKSDKWeakProxy

- (instancetype)initWithTarget:(id)target{
    _target = target;
    return self;
}

+ (instancetype)proxyWithTarget:(id)target{
    return [[self alloc] initWithTarget:target];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    return [self.target methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)invocation{
    SEL sel = [invocation selector];
    if ([self.target respondsToSelector:sel]) {
        [invocation invokeWithTarget:self.target];
    }
}

- (BOOL)respondsToSelector:(SEL)aSelector{
    return [self.target respondsToSelector:aSelector];
}

@end

使用Proxy
 _link = [CADisplayLink displayLinkWithTarget:[TKSDKWeakProxy proxyWithTarget:self] selector:@selector(tick:)];
[_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];

注意事项:在使用定时器的类中需要在dealloc方法中手动释放相关定时器

- (void)dealloc{
    [_link invalidate];
    _link = nil;
}

你可能感兴趣的:(iOS 使用NSProxy来避免循环引用,用在NSTimer或者CADisplayLink中。)