iOS小知识之NSTimer的循环引用三

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

今天继续了解一下切断target强持有的第三种方法

NSProxy虚基类

NSProxy的作用:

  • OC不支持多继承,但是它基于运行时机制,可以通过NSProxy来实现伪多继承
  • NSProxy和NSObject属于同一级别的类,也可以说是一个虚拟类,只实现了NSObject的协议部分
  • NSProxy本质是一个消息转发封装的抽象类,类似一个代理人

可以通过继承NSProxy,并重写以下两个方法实现消息转发

- (void)forwardInvocation:(NSInvocation *)invocation; 

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel;
复制代码

NSProxy除了可以用于多继承,也可以作为切断强持有的中间人 打开LGProxy.h文件,写入以下代码:

#import <Foundation/Foundation.h> 

@interface LGProxy : NSProxy

+ (instancetype)proxyWithTransformObject:(id)object; 

@end
复制代码

打开LGProxy.m文件,写入以下代码:

#import "LGProxy.h" 

@interface LGProxy()

@property (nonatomic, weak) id object;

@end @implementation LGProxy 

+ (instancetype)proxyWithTransformObject:(id)object{ 
    
    LGProxy *proxy = [LGProxy alloc]; 
    proxy.object = object; 
    return proxy; 
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel{ 

    if (!self.object) { 
        NSLog(@"异常收集-stack");
        return nil; 
    } 
    return [self.object methodSignatureForSelector:sel];
}

- (void)forwardInvocation:(NSInvocation *)invocation{ 

    if (!self.object) { 
        NSLog(@"异常收集-stack"); 
        return; 
    }
    [invocation invokeWithTarget:self.object]; 
}

@end
复制代码

LGProxy的调用代码:

- (void)viewDidLoad { 
    [super viewDidLoad];
    
    self.proxy = [LGProxy proxyWithTransformObject:self];
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self.proxy selector:@selector(fireHome) userInfo:nil repeats:YES];
} 

- (void)fireHome{ 
    num++; 
    NSLog(@"hello word - %d",num); 
}

- (void)dealloc{
    [self.timer invalidate]; 
    self.timer = nil; 
}
复制代码
  • LGProxy初始化方法,将传入的object赋值给弱引用对象
  • 再UIViewController中,创建LGProxy对象proxy。创建NSTimer对象,将proxy传入target,避免NSTimer对ViewController强持有。
  • 当NSTimer回调时,触发LGProxy的消息转发方法
    • methodSignatureForSelector:设置方法签名
    • forwardInvocation:自身不做业务处理,将消息转发给object
  • 当页面退出时,ViewController可以正常释放
    • 再dealloc中,对NSTimer进行释放。此时NSTimer对proxy的强持有接触,proxy也跟着释放

猜你喜欢

转载自juejin.im/post/7019455719090946085
今日推荐