引子
半夜突然想写点什么,又不想填之前的坑……因为懒,然后就想到了这个,感觉这应该算是block相关技巧,就根据缺总的提示做了一个测试,顺便再挖下一个大坑,以后遇到有block相关的问题就更新在这里
挖坑这种事嘛,填不填不重要…重要的是要经常挖…
1. block 异步操作执行顺序相关
起因是这个:
66AEA76053CB8DD66B46656F62D1B642.jpg B0F7BE74AFA0E28362230A39764C1283.jpg代码是这样:
0039E5D0D402D4467FA0468E5F58A546.jpg简单的说就是将某个耗时任务塞进队列,必须等到该耗时任务完成后判断某个返回值的状态,然后在主线程中更改预设的BOOL返回值。
但是实际操作中却出现了获取返回值总是先一步于异步线程(block)执行完毕,相当于做了无用功。
打开xcode 随便添加了一个按钮及对应的方法,照着缺总的提示写了一下
1 . 模拟假想情况
- (void)test1 {
NSLog(@"开始测试——————Step.1");
__block BOOL isDone = NO;
dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(defaultQueue, ^{
for (int i = 0; i < 1000000; i++) {
if (i == 999999) {
NSLog(@"循环结束——————Step.2");
isDone = YES;
}
}
});
NSLog(@"执行完毕——————Step.3");
}
测试结果
85988E6F-DB08-4BDD-B11F-B7CA217FE50A.png预料中的结果,耗时操作在 执行完毕后才显示出来
2 . 模拟出现问题的环境……
- (void)test2 {
NSLog(@"开始测试——————Step.1");
__block BOOL isDone = NO;
dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(defaultQueue, ^{
for (int i = 0; i < 1000000; i++) {
if (i == 999999) {
NSLog(@"循环结束——————Step.2");
isDone = YES;
}
}
dispatch_async(dispatch_get_main_queue(), ^{
if (isDone == YES) {
NSLog(@"执行完毕——————Step.3");
}
});
});
NSLog(@"不能判断BOOL值是否已经改变----Step.4");
}
执行结果
23469DFB-F725-4523-B18A-7B58C1D70AD5.png应该就是差不多就是这个样子,尽管在队列里面添加了get_main_queue事件,step.2 step3 也是按照顺序执行了,但是step.4 仍然先一步于异步任务之前执行了。如果说接下来的需要执行的任务塞在step3那个位置不合适的话,那就有些蛋疼了。
3 . **正确的
体位打开方式 **
- (void)test3 {
NSLog(@"开始测试——————Step.1");
__block BOOL isDone = NO;
dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(defaultQueue, ^{
for (int i = 0; i < 1000000; i++) {
if (i == 999999) {
NSLog(@"循环结束——————Step.2");
}
}
isDone = YES;
NSLog(@"执行完毕——————Step.3");
});
while (!isDone) {
NSDate *date = [NSDate distantFuture];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:date];
NSLog(@"唤醒线程");
}
NSLog(@"Next To Do----Step.4");
NSLog(@"%d",isDone);
}
执行结果
D7646AD9-1ECF-45E8-A009-3A1EE7675AC7.png算是达到需要的效果了
唉.png核心思想是 通过runLoop 让封装的block所在线程休眠,而其结果的判断回调会将其唤醒,然后才执行下一步。
话说 NSDate *date = [NSDate distantFuture];
我楞了好久…看着好眼熟,就是想不起来干嘛用的…
我为什么那么喜欢挖坑呢……
8月
逛博客的时候突然看到runloop的一篇文章
1.只有在为你的程序创建次线程的时候,才需要运行run loop。对于程序的主线程而言,run loop是关键部分。Cocoa提供了运行主线程run loop的代码同时也会自动运行run loop。IOS程序UIApplication中的run方法在程序正常启动的时候就会启动run loop。如果你使用xcode提供的模板创建的程序,那你永远不需要自己去启动run loop
2.在多线程中,你需要判断是否需要run loop。如果需要run loop,那么你要负责配置run loop并启动。你不需要在任何情况下都去启动run loop。比如,你使用线程去处理一个预先定义好的耗时极长的任务时,你就可以毋需启动run loop。Run loop只在你要和线程有交互时才需要
配合上面测试的东西有了一点点顿悟的感觉 ,果然还是要结合实际情况,如果光是单纯的这么一段文字我也许看过就忘了。
感觉总结的很好,正是因为与线程发生了交互,才需要对runloop进行一定的操作。
网友评论