当前位置: 移动技术网 > IT编程>移动开发>IOS > IOS开发中延迟执行和取消

IOS开发中延迟执行和取消

2019年07月24日  | 移动技术网IT编程  | 我要评论

residentflash,三国志新传,一生所爱歌词

在 objective-c 中延迟执行还是很常见的需求,通常有如下几种方式可供选择:

performselector:

想要延迟调用某个方法:

[self performselector:@selector(delay) withobject:nil afterdelay:3.0];

取消延迟的方法:

[nsobject cancelpreviousperformrequestswithtarget:self selector:@selector(delay) object:nil];

这里需要注意参数需要保持一致,否则取消失败。

nstimer

想要延迟调用某个方法:

self.timer = [nstimer scheduledtimerwithtimeinterval:2.0 target:self selector:@selector(delay) userinfo:nil repeats:no];

取消延迟的方法:

[self.timer invalidate];
gcd

dispatch_after(dispatch_time(dispatch_time_now, (int64_t)(2.0 * nsec_per_sec)), dispatch_get_main_queue(), ^{
    // ...
});

dispatch_after 是比较常用的方法,但是 objective-c 中并没有提供取消执行的相关 api。我们只能自己实现这个取消的逻辑:

typedef void (^task)(bool cancel);
task delay(nstimeinterval time,void (^task)()) {
  __block void (^closure)() = task;
  __block task result;
  task delayedclosure = ^(bool cancel){
    if (closure) {
      void (^internalclosure)() = closure;
      if (!cancel) {
        dispatch_async(dispatch_get_main_queue(), internalclosure);
      }
    }
    closure = nil;
    result = nil;
  };
  
  result = delayedclosure;
  
  dispatch_after(dispatch_time(dispatch_time_now, (int64_t)(time * nsec_per_sec)), dispatch_get_main_queue(), ^{
    if (delayedclosure) {
      delayedclosure(no);
    }
  });
  return result;
}
使用的话可以这样:

delay(60, ^{
  // ...
});

如果想要延迟,可以先声明成成员变量并赋值:

@property (copy, nonatomic) task task;
self.task = delay(60, ^{
  // ...
});

最后在需要的地方取消就行:

self.task(yes);

这种写法的核心思想是根据传入的 bool 值,来控制 dispatch_after 回调 block 中的方法是否需要执行。看起来是取消了,但实际上还是被 gcd 放到 runloop 里去占用主线程资源了。

dispatch_source

我们还可以利用 dispatch_source 中的定时器,来实现延时/取消操作:

@property (strong, nonatomic) dispatch_source_t timer;
// 队列
dispatch_queue_t queue = dispatch_get_main_queue();
// 创建 dispatch_source
dispatch_source_t timer = dispatch_source_create(dispatch_source_type_timer, 0, 0, queue);
// 声明成员变量
self.timer = timer;
// 设置两秒后触发
dispatch_time_t starttime = dispatch_time(dispatch_time_now, 3.0 * nsec_per_sec);
// 设置下次触发事件为 dispatch_time_forever
dispatch_time_t nexttime = dispatch_time_forever;
// 设置精确度
dispatch_time_t leeway = 0.1 * nsec_per_sec;
// 配置时间
dispatch_source_set_timer(timer, starttime, nexttime, leeway);
// 回调
dispatch_source_set_event_handler(timer, ^{
  // ...
});
// 激活
dispatch_resume(timer);

需要取消的话:

dispatch_source_cancel(self.timer);

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网