我用GCD dispatch_source创建了一个非常简单的计时器,我经常收到这个奇怪的崩溃。代码看起来很好。如果任何人能解释这背后的原因,我会非常高兴。
@interface MyTimer ()
@property (nonatomic, strong, readonly) dispatch_queue_t queue;
@property (nonatomic, readonly) NSTimeInterval timeOutDuration;
@property (nonatomic, copy, readonly) dispatch_block_t callback;
@property (nonatomic, strong) dispatch_group_t group;
@property (nonatomic, strong) dispatch_source_t timer;
@end
@implementation MyTimer
- (instancetype)initWithQueue:(dispatch_queue_t)queue
callback:(dispatch_block_t)callback
timeOutDuration:(NSTimeInterval)interval
{
NSAssert(queue, @"queue must not be nil");
NSAssert(callback, @"callback must not be nil");
if (self = [super init]) {
_queue = queue;
_callback = [callback copy];
_timeOutDuration = interval;
_group = dispatch_group_create();
[self setupTimer];
}
return self;
}
- (void)setupTimer
{
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.queue);
dispatch_source_set_timer(self.timer, dispatch_time(DISPATCH_TIME_NOW, self.timeOutDuration * NSEC_PER_SEC), 0, 0);
__weak typeof(self) weakSelf = self;
dispatch_source_set_event_handler(self.timer, ^{
__strong typeof(self) strongSelf = weakSelf;
// crashes on the next line
dispatch_group_async(strongSelf.group, dispatch_get_main_queue(), strongSelf.callback);
dispatch_group_async(strongSelf.group, strongSelf.queue, ^{
[strongSelf invalidate];
});
});
}
- (void)fire
{
dispatch_resume(self.timer);
}
- (void)invalidate
{
if (self.timer) {
dispatch_source_cancel(self.timer);
_timer = nil;
_callback = nil;
}
}
@end
它通常在此行崩溃,
dispatch_group_async(strongSelf.group, dispatch_get_main_queue(), strongSelf.callback);
崩溃并不总是发生,而是经常发生。我无法理解崩溃背后的逻辑。
答案 0 :(得分:0)
假设定时器将块排队等待执行。当块处于挂起状态时,MyTimer
对象的保留计数变为零,并且MyTimer
被释放。然后弱引用weakSelf
设置为nil。
然后块执行。它会从strongSelf
创建weakSelf
。由于weakSelf
现在为零,strongSelf
也是零。因此strongSelf.group
和strongSelf.callback
都返回nil,并将这些nils传递给dispatch_group_async
。糟糕的节目!没有饼干!
要修复,请在创建后立即检查strongSelf
。如果它是零,只需返回。
我还注意到dealloc
中没有MyTimer
方法。我怀疑保留了恢复的GCD计时器,因此当您MyTimer
被释放时,它不会被无效/释放。您应该添加一个dealloc
[self invalidate]
。