内容简介:更多关于
- (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 。
小结:
-
常用
performSelector
方法-
常用的
perform
,是 NSObject.h 头文件下的方法:- (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelector withObject:(id)object; - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
-
可以 delay 的
perform
,是 NSRunLoop.h 头文件下的方法:- (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;
-
可以 指定线程 的
perform
,是 NSThread 头文件下的方法:- (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;
-
-
RunLoop 退出方式:
-
使用
- (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 就会退出。
-
使用
更多关于 NSRunLoop的退出方式 可以看这篇 博文
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Coding the Matrix
Philip N. Klein / Newtonian Press / 2013-7-26 / $35.00
An engaging introduction to vectors and matrices and the algorithms that operate on them, intended for the student who knows how to program. Mathematical concepts and computational problems are motiva......一起来看看 《Coding the Matrix》 这本书的介绍吧!