iOS:线程保活

2020-08-05  本文已影响0人  春暖花已开
自定义子线程MZChildThread
//MZChildThread.h
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface MZChildThread : NSObject

///在子线程中执行任务
- (void)executeTask:(void(^)(void))task;

///停止并销毁线程
- (void)stopThread;

@end

NS_ASSUME_NONNULL_END

//MZChildThread.m
#import "MZChildThread.h"

#if DEBUG
#ifndef MZPrivateThreadLog
#define MZPrivateThreadLog(...) NSLog(__VA_ARGS__)
#else
#define MZPrivateThreadLog(...)
#endif
#endif

#pragma mark - _MZPrivateThread
@interface MZPrivateThread : NSThread

@end

@implementation MZPrivateThread

- (void)dealloc {
    MZPrivateThreadLog(@"%s", __func__);
}

@end


#pragma mark - MZChildThread

@interface MZChildThread ()

@property (nonatomic, strong) MZPrivateThread *thread;
@property (nonatomic, assign) BOOL shouldStop;

@end

@implementation MZChildThread

#pragma mark - public Methods

- (instancetype)init {
    if (self = [super init]) {

        __weak typeof(self) weakSelf = self;
        self.shouldStop = NO;

        self.thread = [[MZPrivateThread alloc] initWithBlock:^{
            //将端口作为输入源添加到运行循环的指定模式
            [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];

            while (weakSelf && !weakSelf.shouldStop) {
                //相当于run,但又与run不同的是,可以自己控制退出时机
                [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
            }

            //当线程保活时,该打印将被阻塞
            MZPrivateThreadLog(@"===end===");
        }];

        //开启线程
        [self.thread start];
    }
    return self;
}

- (void)executeTask:(void (^)(void))task {

    if (!self.thread || !task) return;

    [self performSelector:@selector(p_executeTask:) onThread:self.thread withObject:task waitUntilDone:NO];
}

- (void)stopThread {

    if (!self.thread) return;

    //waitUntilDone为YES,表示执行完子线程代码后,才执行之后的代码
    [self performSelector:@selector(p_stopThread) onThread:self.thread withObject:nil waitUntilDone:YES];
}


#pragma mark - public Methods

- (void)p_executeTask:(void (^)(void))task {
    task();
}

- (void)p_stopThread {
    self.shouldStop = YES;

    //停止当前线程(一定要在开启的子线程中关闭),之后会解除阻塞
    CFRunLoopStop(CFRunLoopGetCurrent());
    self.thread = nil;
}

- (void)dealloc {
    //在释放的时候,要关闭线程,防止占用资源
    [self stopThread];
    MZPrivateThreadLog(@"%s", __func__);
}

@end
使用
#import "DetailViewController.h"

#import "MZChildThread.h"

@interface DetailViewController ()

@property (nonatomic, strong) MZChildThread *thread;

@end

@implementation DetailViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.thread = [[MZChildThread alloc] init];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    [self.thread executeTask:^{
        NSLog(@"执行任务在 - %@", [NSThread currentThread]);
    }];
}

- (IBAction)stop {
    [self.thread stopThread];
}

- (void)dealloc {
    NSLog(@"%s", __func__);
}

@end
上一篇下一篇

猜你喜欢

热点阅读