内容简介:更多关于
- (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的退出方式 可以看这篇 博文
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
超简单!一学就懂的互联网金融
视觉图文 / 人民邮电出版社 / 2015-2-1 / 45.00元
零基础、全图解,通过130多个精辟的知识点、220多张通俗易懂的逻辑图表,让您一书在手,即可彻底看懂、玩转互联网金融从菜鸟成为达人,从新手成为互联网金融高手! 本书主要特色:最简洁的版式+最直观的图解+最实用的内容。 本书细节特色:10章专题内容详解+80多个特别提醒奉献+130多个知识点讲解+220多张图片全程图解,深度剖析互联网金融的精华之处,帮助读者在最短的时间内掌握互联网金融知......一起来看看 《超简单!一学就懂的互联网金融》 这本书的介绍吧!
HTML 压缩/解压工具
在线压缩/解压 HTML 代码
HEX CMYK 转换工具
HEX CMYK 互转工具