performSelector:onThread:withObject:waitUntilDone理解
直接看代码
//
// ViewController.m
// RunLoopDemo
//
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, assign) BOOL isAborted;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self threadInfo:@"UI"];
_isAborted = NO;
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread:) object:nil];
[thread start];
// When performing a selector on another thread, the target must have an active run loop
[self performSelector:@selector(test:) onThread:thread withObject:nil waitUntilDone:NO];
}
- (void)newThread:(id)obj {
@autoreleasepool {
NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
while (!_isAborted) {
[currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
NSLog(@"线程停止");
}
}
- (void)test:(id)obj {
[self threadInfo:@"test"];
_isAborted = YES;
}
- (void)threadInfo:(NSString *)info {
NSLog(@"%@--%@", info, [NSThread currentThread]);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
有的人无法理解为什么要通过[self performSelector:@selector(test:) onThread:thread withObject:nil waitUntilDone:NO];
中的test:
方法来更新_isAborted
状态。为什么不在[thread start]
之后直接调用。原因其实是这里通过selector方法将其设置成yes的原因是虽然设置为yes,但是这时候runloop所在的线程其实是并不知道_isNewThreadAborted被重新赋值了。runloop没有被任务事件唤醒。所以正确的方法是通过使用selector来唤醒Runloop。 并且要注意,在执行performSelector:onThread:withObject:waitUntilDone
方法时候,如果是在另外一个线程执行,必须保证另外的线程是有一个runloop.具体的使用可以参考AFNetworking.