NSTimer循环引用-破解五法
破解一
-(void)willMoveToParentViewController:(UIViewController *)parent {
if(!parent){
[self.timer invalidate];
self.timer = nil;
}
}
破解二 更换target
NSObject * midOne = [[NSObject alloc] init];
IMP imp = class_getMethodImplementation([self class], @selector(change));
class_addMethod([midOne class], @selector(change),(IMP)imp, "v@:");
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:midOne selector:@selector(change) userInfo:nil repeats:YES];
破解三 更换target ->NSProxy
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:[WeakProxy proxyWithTarget:self] selector:@selector(change) userInfo:nil repeats:YES];
WeakProxy.h
@interface WeakProxy : NSProxy
@property (nonatomic, weak, readonly) id weakTarget;
+ (instancetype)proxyWithTarget:(id)target;
- (instancetype)initWithTarget:(id)target;
@end
WeakProxy.m
#import "WeakProxy.h"
@implementation WeakProxy
+ (instancetype)proxyWithTarget:(id)target {
return [[self alloc] initWithTarget:target];
}
- (instancetype)initWithTarget:(id)target {
_weakTarget = target;
return self;
}
- (void)forwardInvocation:(NSInvocation *)invocation {
SEL sel = [invocation selector];
if ([self.weakTarget respondsToSelector:sel]) {
[invocation invokeWithTarget:self.weakTarget];
}
}
//返回方法的签名。
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [self.weakTarget methodSignatureForSelector:sel];
}
- (BOOL)respondsToSelector:(SEL)aSelector {
return [self.weakTarget respondsToSelector:aSelector];
}
@end
破解四 GCD
dispatch_queue_t queue = dispatch_queue_create(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
self.timeer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
__weak typeof(self) weakself = self;
dispatch_source_set_timer(self.timeer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
dispatch_source_set_event_handler(self.timeer, ^{
dispatch_async(dispatch_get_main_queue(), ^{
[weakself change];
});
});
dispatch_resume(self.timeer);
破解五 NSTimer分类
__weak typeof(self) weakself = self;
self.timer = [NSTimer qgtimerWithTimeInterval:1.f repeats:YES block:^(NSTimer * _Nonnull timer) {
[weakself change];
}];
NSTimer+cycle.h
@interface NSTimer (cycle)
+ (NSTimer *)qgtimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block;
@end
NSTimer+cycle.m
#import "NSTimer+cycle.h"
@implementation NSTimer (cycle)
+ (NSTimer *)qgtimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block {
return [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(blcokInvoke:) userInfo:[block copy] repeats:repeats];
}
+ (void)blcokInvoke:(NSTimer *)timer {
void (^block)(NSTimer *timer) = timer.userInfo;
if (block) {
block(timer);
}
}
@end