#import "AlwaysLiveThread.h" @interface AlwaysLiveThread() { CFRunLoopSourceContext context; CFRunLoopRef runLoop; CFRunLoopSourceRef runLoopSource; } @property (nonatomic, strong) NSThread *workThread; @property (nonatomic, assign) BOOL isStarted; @property (nonatomic, assign) BOOL isStoped; @end @implementation AlwaysLiveThread - (instancetype)init { return [self initWithBlock:^{ }]; } - (instancetype)initWithBlock:(void (^)(void))block { self = [super init]; if (self) { self.isStarted = NO; self.isStoped = NO; self.workThread = [[NSThread alloc] initWithTarget:self selector:@selector(startThreadByBlock:) object:block]; } return self; } - (BOOL)startThisThread { BOOL isStarted = self.isStarted; if (!self.isStarted && !self.isStoped) { [self.workThread start]; } return (!self.isStoped && !isStarted); } - (void)startThreadByBlock:(void (^)(void))block { if (!self.isStarted && !self.isStoped) { !block?:block(); [self registerRunloopSourceThenRunning]; } } - (void)registerRunloopSourceThenRunning { if (!self.isStarted && !self.isStoped) { self.isStarted = YES; runLoop = CFRunLoopGetCurrent(); runLoopSource = CFRunLoopSourceCreate(NULL, 0, &context); CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopDefaultMode); CFRunLoopRun(); } } - (void)stopThisRunloopWhileDisableThread { if (!self.isStoped && self.isStarted) { CFRunLoopStop(runLoop); CFRunLoopRemoveSource(runLoop, runLoopSource, kCFRunLoopDefaultMode); CFRelease(runLoopSource); CFRelease(&context); self.isStoped = YES; } } - (void)workJob:(void (^)(void))block { [self performSelector:@selector(doNewJob:) onThread:self.workThread withObject:block waitUntilDone:NO]; } - (void)doNewJob:(void (^)(void))block { !block?:block(); } - (BOOL)stopThisThread { BOOL isStoped = self.isStoped; if (self.isStarted && !self.isStoped) { /// 放在线程内执行,主要是避免跨线程操作异常(比如调用启动后立即停止,导致数据访问异常) [self performSelector:@selector(stopThisRunloopWhileDisableThread) onThread:self.workThread withObject:nil waitUntilDone:NO]; } return (self.isStarted && !isStoped); } - (void)dealloc { #ifdef DEBUG NSLog(@"任务线程%@被销毁",self); #endif } @end
原文:https://www.cnblogs.com/yuxiaoyiyou/p/13162748.html