block 备忘录
引子
半夜突然想写点什么,又不想填之前的坑……因为懒,然后就想到了这个,感觉这应该算是block相关技巧,就根据缺总的提示做了一个测试,顺便再挖下一个大坑,以后遇到有block相关的问题就更新在这里
![](https://img.haomeiwen.com/i1496281/f700af7a8491294c.png)
挖坑这种事嘛,填不填不重要…重要的是要经常挖…
1. block 异步操作执行顺序相关
起因是这个:
![](https://img.haomeiwen.com/i1496281/39c6e4f98522ce23.jpg)
![](https://img.haomeiwen.com/i1496281/deeec8710d53da71.jpg)
代码是这样:
![](https://img.haomeiwen.com/i1496281/1888f468f90c8554.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");
}
测试结果
![](https://img.haomeiwen.com/i1496281/5758b39a469c5e43.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");
}
执行结果
![](https://img.haomeiwen.com/i1496281/eef8cfaf9509f2f5.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);
}
执行结果
![](https://img.haomeiwen.com/i1496281/abd0f87d3b8d930b.png)
算是达到需要的效果了
核心思想是 通过runLoop 让封装的block所在线程休眠,而其结果的判断回调会将其唤醒,然后才执行下一步。
![](https://img.haomeiwen.com/i1496281/ef2d2845d37d1343.png)
话说 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进行一定的操作。