asunquan.com

不忘初心 不止于行

职场新人 iOS菜鸟 就职于搜狐畅游 从事iOS/tvOS的SDK开发 对于游戏市场有点点了解 平日和一只小Corgi同吃同睡


[转]面试题: 创建一个可以被取消执行的block

题目

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

typedef void(^Block)();

@interface CancelableObject : NSObject

- (id)initWithBlock:(Block)block;
- (void)start;
- (void)cancel;

@end

分析及答案

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

    @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 执行中的代码是通过参数传递进来的话, 似乎并没有什么办法可以修改它了.

最近的文章

[转改]面试题: 按层遍历二叉树的节点(Objective-C版)

题目**给你一棵二叉树, 请按层输出其的节点值, 即: 从上到下, 从左到右的顺序. 例如, 如果给你如下一棵二叉树: ** 3 / \ 9 20 / \ 15 7输出结果应该是:[ [3], [9, 20], [15, 7] ]分析及答案 二叉树节点定义 采用单链表的形式, 只从根节点指向子节点, 不保存父节点 @interface BinaryTreeNode : NSObject/** 该节点的值 */@proper...…

iOS开发面试题继续阅读
更早的文章

一些常见的面试题[持续更新]

[TOC]前言人挪死, 树挪活. 恰逢最近准备挪下窝, 虽然没有开始投递简历, 但是也看了些面试的内容, 做个总结, 权当为了以后复习节省时间.面试题基础关键字属性的修饰关键字关于修饰属性的关键字可以分为以下几部分: 关于线程安全: atomic, nonatomic 关于读写权限: readwrite, readonly 关于属性内存: weak, strong, copy, assign, retain 关于对象为空: nullable, nonnullnonatomic和at...…

iOS开发面试题继续阅读