本文首发在个人我的博客: blog.shenyuanluo.com,喜欢的朋友欢迎订阅。html
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
withObject:nil];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
复制代码
1,2,3,4
performSelector:withObject:
会在当前线程当即执行指定的 selector 方法。- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
withObject:nil
afterDelay:0];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
复制代码
1,2,4
performSelector:withObject:afterDelay:
实际是往 RunLoop 里面注册一个定时器,而在子线程中,RunLoop 是没有开启(默认)的,全部不会输出 3
。官网 API 做以下解释:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
withObject:nil
afterDelay:0];
[[NSRunLoop currentRunLoop] run];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
复制代码
1,2,3,4
[[NSRunLoop currentRunLoop] run];
会建立的当前子线程对应的 RunLoop 对象并启动了,所以能够执行 test
方法;而且 test
执行完后,RunLoop 中注册的定时器已经无效,因此还能够输出 4
(对比 例子⑥例子)。- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
onThread:[NSThread currentThread]
withObject:nil
waitUntilDone:YES];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
复制代码
1,2,3,4
performSelector:onThread:withObject:waitUntilDone:
会在指定的线程执行,而执行的策略根据参数 wait
处理,这里传 YES
代表将会当即阻断 指定的线程 并执行指定的 selector
。官网 API 解释以下:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
onThread:[NSThread currentThread]
withObject:nil
waitUntilDone:NO];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
复制代码
1,2,4
performSelector:onThread:withObject:waitUntilDone:
会在指定的线程执行,而执行的策略根据参数 wait
处理,这里传 NO
代表不会当即阻断 指定的线程 而是将 selector
添加到指定线程的 RunLoop 中等待时机执行。(该例子中,子线程 RunLoop 没有启动,全部没有输出 3
)官网 API 解释以下:- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
onThread:[NSThread currentThread]
withObject:nil
waitUntilDone:NO];
[[NSRunLoop currentRunLoop] run];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
复制代码
1,2,3
[[NSRunLoop currentRunLoop] run];
已经建立的当前子线程对应的 RunLoop 对象并启动了,所以能够执行 test
方法;可是 test
方法执行完后,RunLoop 并无结束(使用这种启动方式,RunLoop 会一直运行下去,在此期间会处理来自输入源的数据,而且会在 NSDefaultRunLoopMode
模式下重复调用 runMode:beforeDate:
方法)因此没法继续输出 4
。- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
onThread:[NSThread currentThread]
withObject:nil
waitUntilDone:NO];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
复制代码
1,2,3
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
已经建立的当前子线程对应的 RunLoop 对象并启动了,所以能够执行 test
方法;可是 test
方法执行完后,RunLoop 并无结束(使用这种启动方式,能够设置超时时间,在超时时间到达以前,runloop会一直运行,在此期间runloop会处理来自输入源的数据,而且会在 NSDefaultRunLoopMode
模式下重复调用 runMode:beforeDate:
方法)因此没法继续输出 4
。- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"1 - %@", [NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2 - %@", [NSThread currentThread]);
[self performSelector:@selector(test)
onThread:[NSThread currentThread]
withObject:nil
waitUntilDone:NO];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
NSLog(@"4 - %@", [NSThread currentThread]);
});
}
- (void)test
{
NSLog(@"3 - %@", [NSThread currentThread]);
}
复制代码
1,2,3,4
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
已经建立的当前子线程对应的 RunLoop 对象并启动了,所以能够执行 test
方法;并且 test
方法执行完后,RunLoop 马上结束(使用这种启动方式 ,RunLoop 会运行一次,超时时间到达或者第一个 input source
被处理,则 RunLoop 就会退出)因此能够继续输出 4
。- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
复制代码
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSRunLoopMode> *)modes;
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
复制代码
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg;
复制代码
- (void)run;
启动,RunLoop 会一直运行下去,在此期间会处理来自输入源的数据,而且会在 NSDefaultRunLoopMode
模式下重复调用 runMode:beforeDate:
方法;- (void)runUntilDate:(NSDate *)limitDate;
启动,能够设置超时时间,在超时时间到达以前,RunLoop 会一直运行,在此期间 RunLoop 会处理来自输入源的数据,而且也会在 NSDefaultRunLoopMode
模式下重复调用 runMode:beforeDate:
方法;- (void)runMode:(NSString *)mode beforeDate:(NSDate *)limitDate;
启动,RunLoop 会运行一次,超时时间到达或者第一个 input source
被处理,则 RunLoop 就会退出。