我正在使用 Objective-C 开发 iOS 框架。
我使用
dispatch_queue_t
创建了一个 dispatch_queue_create
。并调用 CFRunLoopRun()
来运行队列中的 runloop。
但是,看起来dispatch_queue_t共享了RunLoop。有些类添加了无效的计时器,当我调用
CFRunLoopRun()
时,它在我这边崩溃了。
- (void)viewDidLoad {
[super viewDidLoad];
self.queue1 = dispatch_queue_create("com.queue1", DISPATCH_QUEUE_CONCURRENT);
self.queue2 = dispatch_queue_create("org.queue2", DISPATCH_QUEUE_CONCURRENT);
}
- (IBAction)btnButtonAction:(id)sender {
dispatch_async(self.queue1, ^{
NSString *runloop = [NSString stringWithFormat:@"%@", CFRunLoopGetCurrent()];
runloop = [runloop substringWithRange:NSMakeRange(0, 22)];
NSLog(@"Queue1 %p run: %@", self.queue1, runloop);
//NSTimer *timer = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:1 target:self selector:@selector(wrongSeletor:) userInfo:nil repeats:NO];
//[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
});
dispatch_async(self.queue2, ^{
NSString *runloop = [NSString stringWithFormat:@"%@", CFRunLoopGetCurrent()];
runloop = [runloop substringWithRange:NSMakeRange(0, 22)];
NSLog(@"Queue2 %p run: %@", self.queue2, runloop);
CFRunLoopRun();
});
}
有时他们采用相同的 RunLoop:
======
您可以通过取消注释
NSTimer
的代码来看到崩溃。 queue1
中已经添加了NSTimer,但是在CFRunLoopRun()
中调用queue2
时它仍在运行。
我读过一些描述,例如:需要一些关于调度队列、线程和 NSRunLoop 的说明
他们这么说:
system creates a run loop for the thread
。但是,在我的检查中,他们正在共享 RunLoop。
这对我来说很伤心,因为我在生产中调用
CFRunLoopRun()
时会发生崩溃。
如果你想在调度队列上运行某些东西,我们通常不会使用
NSTimer
。相反,我们将使用调度计时器。这根本不需要运行循环。
与
NSTimer
不同,我们需要保留对计时器的强引用:
@property (nonatomic, strong) dispatch_source_t timer;
然后,启动计时器:
- (void)startTimer {
dispatch_queue_t queue = dispatch_queue_create("com.domain.app.timer", DISPATCH_QUEUE_SERIAL);
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(self.timer, ^{
// this is called when the timer fires
});
dispatch_resume(self.timer);
}
要停止计时器,只需松开它即可:
- (void)stopTimer {
self.timer = nil;
}