美文网首页
iOS 面试题(九):创建一个可以被取消执行的 block

iOS 面试题(九):创建一个可以被取消执行的 block

作者: 凯旋之歌 | 来源:发表于2017-08-19 10:06 被阅读0次

问题:

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

相关文章

网友评论

      本文标题:iOS 面试题(九):创建一个可以被取消执行的 block

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