zoukankan      html  css  js  c++  java
  • 创建一个可以被取消执行的 block

    问题

    我们知道 block 默认是不能被取消掉的,请你封装一个可以被取消执行的 block wrapper 类,它的定义如下:

    typedef void (^Block)();
    
    @interface CancelableObject : NSObject
    
    - (id)initWithBlock:(Block)block;
    - (void)start;
    - (void)cancel;
    
    @end

    |
    |
    |
    |
    |
    |
    |
    |
    | 思考时间,想好了请往下翻答案。
    |
    |
    |
    |
    |
    |
    |
    |
    |

    答案

    这道题是从网上看到的,原题是创建一个可以取消执行的 block,我想到两种写法。

    方法一:创建一个类,将要执行的 block 封装起来,然后类的内部有一个 _isCanceled 变量,在执行的时候,检查这个变量,如果 _isCanceled 被设置成 YES 了,则退出执行。

    typedef void (^Block)();
    
    @interface CancelableObject : NSObject
    
    - (id)initWithBlock:(Block)block;
    - (void)start;
    - (void)cancel;
    
    @end
    
    @implementation CancelableObject {
        BOOL _isCanceled;
        Block _block;
    }
    
    - (id)initWithBlock:(Block)block {
        self = [super init];
        if (self != nil) {
            _isCanceled = NO;
            _block = block;
        }
        return self;
    }
    
    - (void)start {
        __weak typeof(self) weakSelf = self;
        dispatch_async(dispatch_get_global_queue(0, 0), 
          ^{        if (weakSelf) {           typeof(self) strongSelf = weakSelf;           if (!strongSelf->_isCanceled) {               (strongSelf->_block)();           }        }    }); } - (void)cancel {    _isCanceled = YES; } @end

    另外一种写法,将要执行的 block 直接放到执行队列中,但是让其在执行前检查另一个 isCanceled 的变量,然后把这个变量的修改实现在另一个 block 方法中,如下所示:

    typedef void (^CancelableBlock)();
    typedef void (^Block)();
    
    + (CancelableBlock)dispatch_async_with_cancelable:(Block)block {
    
        __block BOOL isCanceled = NO;
        CancelableBlock cb = ^() {
            isCanceled = YES;
        };
    
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            if (!isCanceled) {
                block();
            }
        });
    
        return cb;
    }

    以上两种方法都只能在 block 执行前有效,如果要在 block 执行中有效,只能让 block 在执行中,有一个机制来定期检查外部的变量是否有变化,而要做到这一点,需要改 block 执行中的代码。在本例中,如果 block 执行中的代码是通过参数传递进来的话,似乎并没有什么办法可以修改它了。

    如果大家有更好的实现方法,欢迎留言告诉我。

  • 相关阅读:
    浅谈3次登录错误
    JDK一键安装,配置环境
    火炬之光2_辅助工具 内存读写相关
    学习资料
    如何在google colab加载kaggle数据
    Trie树
    日常
    Kmeans
    【leet-code】135. 加油站
    Mac CLion下OpenGL环境配置
  • 原文地址:https://www.cnblogs.com/pioneerMax/p/6420437.html
Copyright © 2011-2022 走看看