总结了四种解决方案,与君共享
1、使用类方法
@interface TimerTarget : NSObject
@property (nonatomic, assign) SEL selector;
@property (nonatomic, weak) NSTimer *timer;
@property (nonatomic, weak) id target;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval target:(id)target selector:(SEL)selector userInfo:(nullable id)userInfo repeats:(BOOL)repeats;
@end
#import "TimerTarget.h"
@implementation TimerTarget
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval target:(id)target selector:(SEL)selector userInfo:(nullable id)userInfo repeats:(BOOL)repeats {
TimerTarget *timerTarget = [[TimerTarget alloc] init];
timerTarget.target = target;
timerTarget.selector = selector;
timerTarget.timer = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:timerTarget selector:@selector(timerSelector:) userInfo:userInfo repeats:repeats];
return timerTarget.timer;
}
- (void)timerSelector:(NSTimer *)timer {
if (self.target && [self.target respondsToSelector:self.selector]) {
[self.target performSelector:self.selector withObject:timer.userInfo];
} else {
[self.timer invalidate];
}
}
- (void)dealloc {
printf(__func__);
}
@end
@interface TimerController ()
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation TimerController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(20, 100, self.view.frame.size.width - 40, 40);
button.backgroundColor = [UIColor greenColor];
[button setTitle:@"倒计时" forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
- (void)buttonAction {
self.timer = [TimerTarget scheduledTimerWithTimeInterval:2 target:self selector:@selector(timeFire) userInfo:nil repeats:YES];
[self.timer setFireDate:[NSDate distantPast]];
}
- (void)timeFire {
NSLog(@"开始计时");
}
- (void)dealloc {
[self.timer invalidate];
printf(__func__);
}
2、创建一个NSProxy的子类
@interface TimerProxy : NSProxy
@property (nonatomic, weak) id weakTarget;
- (instancetype)initWithTarget:(id)target;
+ (instancetype)proxyWithTarget:(id)target;
@end
#import "TimerProxy.h"
@implementation TimerProxy
- (instancetype)initWithTarget:(id)target {
_weakTarget = target;
return self;
}
+ (instancetype)proxyWithTarget:(id)target {
return [[self alloc] initWithTarget:target];
}
//返回方法的签名。
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
return [self.weakTarget methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation {
SEL sel = [invocation selector];
if ([self.weakTarget respondsToSelector:sel]) {
[invocation invokeWithTarget:self.weakTarget];
}
}
- (BOOL)respondsToSelector:(SEL)aSelector {
return [self.weakTarget respondsToSelector:aSelector];
}
@end
@interface TimerController ()
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation TimerController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(20, 100, self.view.frame.size.width - 40, 40);
button.backgroundColor = [UIColor greenColor];
[button setTitle:@"倒计时" forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
- (void)buttonAction {
self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:[TimerProxy proxyWithTarget:self] selector:@selector(timeFire) userInfo:nil repeats:YES];
[self.timer setFireDate:[NSDate distantPast]];
}
- (void)timeFire {
NSLog(@"开始计时");
}
- (void)dealloc {
[self.timer invalidate];
printf(__func__);
}
3、使用Block
@interface NSTimer (WeakTimer)
+ (NSTimer *)jf_scheduledTimerWithTimeInterval:(NSTimeInterval)interval
repeats:(BOOL)repeats
block:(void(^)(void))block;
@end
#import "NSTimer+WeakTimer.h"
@implementation NSTimer (WeakTimer)
+ (NSTimer *)jf_scheduledTimerWithTimeInterval:(NSTimeInterval)interval
repeats:(BOOL)repeats
block:(void(^)(void))block {
return [self scheduledTimerWithTimeInterval:interval
target:self
selector:@selector(jf_blockInvoke:)
userInfo:[block copy]
repeats:repeats];
}
+ (void)jf_blockInvoke:(NSTimer *)timer {
void (^block)(void) = timer.userInfo;
if(block) {
block();
}
}
@end
//创建timer
__weak typeof(self) weakSelf = self;
self.timer = [NSTimer jf_scheduledTimerWithTimeInterval:2 repeats:YES block:^{
[weakSelf timeFire];
}];
4、GCD的timer替换
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
self.aTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(_aTimer, dispatch_time(DISPATCH_TIME_NOW, 0), 2 * NSEC_PER_SEC, 0);
dispatch_source_set_event_handler(_aTimer, ^{
NSLog(@"%@", [NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"开始计时");
});
});
//开启计时器
dispatch_resume(_aTimer);
//结束计时
//dispatch_source_cancel(_aTimer);
本文分享了四种解决计时器问题的方法:使用类方法、创建NSProxy子类、使用Block和GCD的timer替换,每种方法都有详细的代码实现。
887

被折叠的 条评论
为什么被折叠?



