美文网首页
block 备忘录

block 备忘录

作者: 芙箩娅 | 来源:发表于2016-08-12 06:00 被阅读26次

    引子

    半夜突然想写点什么,又不想填之前的坑……因为懒,然后就想到了这个,感觉这应该算是block相关技巧,就根据缺总的提示做了一个测试,顺便再挖下一个大坑,以后遇到有block相关的问题就更新在这里

    不知不觉中好像又挖了一个大坑…….png

    挖坑这种事嘛,填不填不重要…重要的是要经常挖…

    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

    算是达到需要的效果了

    核心思想是 通过runLoop 让封装的block所在线程休眠,而其结果的判断回调会将其唤醒,然后才执行下一步。

    唉.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进行一定的操作。

    相关文章

      网友评论

          本文标题:block 备忘录

          本文链接:https://www.haomeiwen.com/subject/sjissttx.html