NSRunLoop保活之销毁LSThread对象

https://www.jianshu.com/p/b218d2921035
这篇文章给出了线程保活的方法,但却有一个LSThread对象没有销毁的问题,这篇文章解决这个问题。

为什么线程对象没有销毁?

之所以线程对象没有销毁是因为RunLoop还没有结束。

[[NSRunLoop currentRunLoop] run];

开启RunLoop的这个方法是一个无限循环的,一旦开启之后就无法停止,所以我们需要更换方法。

  [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];

这是一个只开启RunLoop一次的方法,但并不能直接使用,否则保活线程也只能保活一次了。
设置一个是否停止线程的标识符stopped,更改后的代码:

  while (!weakSelf.isStoped) {
         [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];   // 只开启一次RunLoop
     }

停止线程

停止线程的操作需要在要停止的线程下进行,代码

  - (void)stop{
[self performSelector:@selector(stopThread) onThread:self.thread withObject:nil waitUntilDone:YES];
}
- (void)stopThread{
self.stopped = YES;
CFRunLoopStop(CFRunLoopGetCurrent());
self.thread = nil;
}

这样我们在停止线程之后LSThread对象就会被销毁掉,当退出当前控制器当前控制器就会被销毁掉。

直接退出当前控制器仍然能结束线程

此时还有一个问题,就是在不停止线程的时候直接退出当前控制器,线程仍然不能停止,这是为什么呢?

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

我们已经在控制器的dealloc方法中调用了停止线程的stop方法,可仍不管用。
还是无限开启RunLoop那块的问题,看代码:

while (!weakSelf.isStoped) {
     [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];   // 只开启一次RunLoop
 }

只要停止线程的标识为NO就开启RunLoop,当我们直接退出当前控制器当前控制器被销毁,其持有的stopped属性也会置为nil,此时的while判断条件也是成立的所以还会开启RunLoop。那么此时要怎么做才对呢?看代码:

  while (weakSelf && !weakSelf.isStoped) {
         [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];   // 只开启一次RunLoop
     }。

当当前控制器不为nil且停止线程的标识为NO的时候才开启RunLoop。

注意:

[self performSelector:@selector(stopThread) onThread:self.thread withObject:nil waitUntilDone:YES];

该方法中最后一个参数的函数,
YES:等待子线程中的操作完成后再继续执行
NO:不等待子线程中的操作完成就直接继续执行

参考demo:https://gitee.com/liangsenliangsen/thread_preserving

你可能感兴趣的:(NSRunLoop保活之销毁LSThread对象)