iOS - Runloop在实际开发中的应用

iOS - Runloop在实际开发中的应用

1. 控制线程生命周期(线程保活)

如果需要经常在子程序执行任务,可能希望一个线程可以重复使用,避免每次都要创建、销毁带来不必要的开销

ZSXPermenantThread.h

objectivec 复制代码
typedef void (^ZSXPermenantThreadTask)(void);

@interface ZSXPermenantThread : NSObject

/**
 开启线程
 */
//- (void)run;

/**
 在当前子线程执行一个任务
 */
- (void)executeTask:(ZSXPermenantThreadTask)task;

/**
 结束线程
 */
- (void)stop;

@end

ZSXPermenantThread.m

objectivec 复制代码
#import "ZSXPermenantThread.h"

/** ZSXThread **/
@interface ZSXThread : NSThread
@end
@implementation ZSXThread
- (void)dealloc
{
    NSLog(@"%s", __func__);
}
@end

/** ZSXPermenantThread **/
@interface ZSXPermenantThread()

@property (strong, nonatomic) ZSXThread *innerThread;
@property (assign, nonatomic, getter=isStopped) BOOL stopped;

@end

@implementation ZSXPermenantThread

#pragma mark - public methods
- (instancetype)init {
    if (self = [super init]) {
        self.stopped = NO;
        
        __weak typeof(self) weakSelf = self;
        
        self.innerThread = [[ZSXThread 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:(ZSXPermenantThreadTask)task {
    if (!self.innerThread || !task) return;
    
    [self performSelector:@selector(__executeTask:) onThread:self.innerThread withObject:task waitUntilDone:NO];
}

- (void)stop {
    if (!self.innerThread) return;
    
    [self performSelector:@selector(__stop) onThread:self.innerThread withObject:nil waitUntilDone:YES];
}

- (void)dealloc {
    NSLog(@"%s", __func__);
    
    [self stop];
}

#pragma mark - private methods
- (void)__stop {
    self.stopped = YES;
    CFRunLoopStop(CFRunLoopGetCurrent());
    self.innerThread = nil;
}

- (void)__executeTask:(ZSXPermenantThreadTask)task {
    task();
}

@end

在 ViewController中使用

less 复制代码
@interface ViewController ()

@property (strong, nonatomic) ZSXPermenantThread *thread;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.thread = [[ZSXPermenantThread alloc] init];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self.thread executeTask:^{        NSLog(@"执行任务 - %@", [NSThread currentThread]);
    }];
}


- (IBAction)stop:(UIButton *)sender {
    [self.thread stop];
}


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

@end

运行结果:

2. 解决NSTimer在滑动时停止工作的问题

2.1. 案例

使用NSTimer创建一个定时器,循环打印

objectivec 复制代码
[NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
    NSLog(@"%d", ++count);
}];

当scrollView 滚动时,定时器就停止了

2.2 解决

objectivec 复制代码
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"%d", ++count);
    }];
//    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
//    [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

// NSDefaultRunLoopMode、UITrackingRunLoopMode 才是真正存在的模式
// NSRunLoopCommonModes 并不是一个真的模式,它只是一个标记而已
// time 能在_commonModes数组中存放的的模式下工作。也就是包含NSDefaultRunLoopMode、UITrackingRunLoopMode
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

3. 监控应用卡顿

4. 性能优化

@oubijiexi

相关推荐
HLC++5 小时前
Linux的进程间通信
android·linux·服务器
华清远见IT开放实验室7 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设
groundhappy9 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕10 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫11 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生11 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
imc.1113 小时前
linux基础IO
linux·运维·服务器
BelongPanda14 小时前
Linux Nginx 纯手动 Let‘s Encrypt 泛域名证书配置教程
linux·nginx
酷可达拉斯15 小时前
Linux操作系统-shell编程(0)
linux·运维·服务器·python·云计算
2301_7779983415 小时前
Linux中断机制:操作系统如何高效运行
linux·运维·服务器