介紹
在日常的iOS開(kāi)發(fā)中蹂窖,遇到卡頓也是在所難免猜年,一般卡頓是由于主線程處理耗時(shí)長(zhǎng)的操作而造成線程一直在阻塞抡锈,那么我們可以去建立子線程,把耗時(shí)操作放在子線程去做乔外,這樣是完全沒(méi)問(wèn)題床三。 這樣就會(huì)有一個(gè)問(wèn)題,子線程處理完操作之后就會(huì)被銷毀杨幼,想再處理其他事情撇簿,必須再開(kāi)啟新的子線程。如果想要一個(gè)子線程去持續(xù)處理事情差购,那么就需要這個(gè)線程一直存活在后臺(tái)四瘫,在需要的時(shí)候隨時(shí)可以喚醒。
下面提供兩種線程庇樱活的方案就可以做到闭颐郏活,在有任務(wù)的時(shí)候喚醒來(lái)做事情稳析, 線程沒(méi)任務(wù)時(shí)會(huì)進(jìn)入休眠狀態(tài)洗做。
方案一
//頭文件
typedef void (^YZCPermenantThreadTask)(void);
@interface YZCPermenantThread : NSObject
- (void)executeTask:(YZCPermenantThreadTask)task;
- (void)cancelTask;
@end
//==========.m文件================
#import "YZCPermenantThread.h"
#pragma mark - YZCThread
@interface YZCThread : NSThread
@end
@implementation YZCThread
-(void)dealloc {
NSLog(@"%s",__func__);
}
@end
#pragma mark - YZCPermenantThread
@interface YZCPermenantThread()
@property (nonatomic, strong) YZCThread *innerThread;
@property (nonatomic, assign, getter=isStopped) BOOL stopped;
@end
@implementation YZCPermenantThread
- (instancetype)init
{
self = [super init];
if (self) {
self.stopped = NO;
__weak typeof(self) weakSelf = self;
self.innerThread = [[YZCThread alloc] initWithBlock:^{
[[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init]
forMode:NSDefaultRunLoopMode];
while (weakSelf && !weakSelf.isStopped) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
}
}];
[self.innerThread start];
}
return self;
}
- (void)executeTask:(YZCPermenantThreadTask)task {
if (!self.innerThread || !task) return;
[self performSelector:@selector(__executeTask:) onThread:self.innerThread
withObject:task waitUntilDone:NO];
}
- (void)cancelTask {
if (!self.innerThread) return;
[self performSelector:@selector(stop) onThread:self.innerThread
withObject:nil waitUntilDone:YES];
}
#pragma mark - private
- (void)stop {
self.stopped = YES;
CFRunLoopStop(CFRunLoopGetCurrent());
self.innerThread = nil;
}
- (void)__executeTask:(YZCPermenantThreadTask)task {
task();
}
方案二
方案二只是核心實(shí)現(xiàn)不一樣,其他基本一致迈着,相比方案一去除了標(biāo)記竭望,直接使用CFRunLoop
去做
- (instancetype)init
{
if (self = [super init]) {
self.innerThread = [[YZCPermenantThread alloc] initWithBlock:^{
NSLog(@"begin----");
// 創(chuàng)建上下文(要初始化一下結(jié)構(gòu)體)
CFRunLoopSourceContext context = {0};
// 創(chuàng)建source
CFRunLoopSourceRef source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
// 往Runloop中添加source
CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
// 銷毀source
CFRelease(source);
// 啟動(dòng)
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0e10, false);
NSLog(@"end----");
}];
[self.innerThread start];
}
return self;
}
調(diào)用
外面調(diào)用就相對(duì)比較簡(jiǎn)單邪码,因?yàn)樯厦嬉呀?jīng)封裝好了
#import "ViewController.h"
#import "YZCPermenantThread.h"
@interface ViewController ()
@property (nonatomic, strong) YZCPermenantThread *thread;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.thread = [[YZCPermenantThread alloc] init];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.thread executeTask:^{
NSLog(@"執(zhí)行了任務(wù):%@",[NSThread currentThread]);
}];
}