IOS开发中延迟执行和取消

在 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);

您可能感兴趣的文章:

  • iOS延迟执行方法详解
  • 对比分析iOS延迟执行的4种方式
(0)

相关推荐

  • iOS延迟执行方法详解

    近日学习了延迟执行的几种方法,分享一下. 1.performSelector(NSObject)方法  2.NSTimer方法  3.GCD方法  4.sleep(NSThread)方法 延迟执行代码: - (void)delayDo : (id)sender { NSLog(@"do:%@",sender); } 1.performSelector(NSObject)方法 这是iOS中常用的一种延迟执行方法. 特点:这个方法必须要在主线程中使用.可以传递参数.可以取消操作,不能暂停.

  • 对比分析iOS延迟执行的4种方式

    最近学习了延迟执行的几种方法,分享一下: 1.performSelector(NSObject)方法  2.NSTimer方法  3.GCD方法  4.sleep(NSThread)方法 一.performSelector方法: 复制代码 代码如下: [self performSelector:@selector(delayMethod) withObject:nil afterDelay:1.0f]; 1.特点: 此方式要求必须在主线程中执行,否则无效. 是一种非阻塞的执行方式, 暂时未找到取

  • IOS开发中延迟执行和取消

    在 Objective-C 中延迟执行还是很常见的需求,通常有如下几种方式可供选择: performSelector: 想要延迟调用某个方法: [self performSelector:@selector(delay) withObject:nil afterDelay:3.0]; 取消延迟的方法: [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delay) object:nil]; 这里需要

  • IOS开发中加载大量网络图片优化方法

    IOS开发中加载大量网络图片如何优化 1.概述 在IOS下通过URL读一张网络图片并不像其他编程语言那样可以直接把图片路径放到图片路径的位置就ok,而是需要我们通过一段类似流的方式去加载网络图片,接着才能把图片放入图片路径显示.比如: -(UIImage *) getImageFromURL:(NSString *)fileURL { //NSLog(@"执行图片下载函数"); UIImage * result; NSData * data = [NSData dataWithCont

  • iOS开发中使用UIScrollView实现无限循环的图片浏览器

    一.概述 UIKit框架中有大量的控件供开发者使用,在iOS开发中不仅可以直接使用这些控件还可以在这些控件的基础上进行扩展打造自己的控件.在这个系列中如果每个控件都介绍一遍确实没有必要,所谓授人以鱼不如授人以渔,这里会尽可能让大家明白其中的原理,找一些典型的控件进行说明,这样一来大家就可以触类旁通.今天我们主要来看一下UIScrollView的内容: UIView UIScrollView 实战--图片浏览器 二.UIView 在熟悉UIScrollView之前很有必要说一下UIView的内容.

  • iOS开发中指纹识别简单介绍

    ios开发中指纹识别简单介绍,在iphone系列中,是从5S以后开始有了指纹识别的功能,在ios8的时候开放的指纹验证的接口. 所以我们在进行指纹识别应用的时候要去判断机型以及系统的版本. 代码如下,下面需要特别注意的其实就是LAPolicyDeviceOwnerAuthentication和LAPolicyDeviceOwnerAuthenticationWithBiometrics的区别,以及检测系统的版本通过[UIDevice currentDevice].systemVersion.fl

  • 浅谈iOS开发中static变量的三大作用

    (1)先来介绍它的第一条也是最重要的一条:隐藏 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性.为理解这句话,我举例来说明.我们要同时编译两个源文件,一个是a.c,另一个是main.c. 下面是a.c的内容 char a = 'A'; // global variable void msg() { printf("Hello\n"); } 下面是main.c的内容 int main(void) { extern char a; // extern v

  • 详解IOS开发中生成推送的pem文件

    详解IOS开发中生成推送的pem文件 具体步骤如下: 首先,需要一个pem的证书,该证书需要与开发时签名用的一致. 具体生成pem证书方法如下: 1. 登录到 iPhone Developer Connection Portal(http://developer.apple.com/iphone/manage/overview/index.action )并点击 App IDs 2. 创建一个不使用通配符的 App ID .通配符 ID 不能用于推送通知服务.例如,  com.itotem.ip

  • IOS 开发中画扇形图实例详解

    IOS 开发中画扇形图实例详解 昨天在做项目中,遇到一个需要显示扇形图的功能,网上搜了一下,发现code4app里面也没有找到我想要的那种类似的效果,没办法了,只能自己学习一下如何画了. 首先我们需要了解一个uiview的方法 -(void)drawRect:(CGRect)rect 我们知道了这个方法,就可以在自定义UIView的子类的- (void)drawRect:(CGRect)rect里面绘图了,关于drawrect的调用周期,网上也是一找一大堆,等下我会整理一下,转载一篇供你们参考.

  • IOS开发中异步网络请求上实现同步逻辑

    IOS开发中异步网络请求上实现同步逻辑 前提: 可能遇到一些问题,比如上传多个数据,需要等多个数据上传成功后做一定的处理,而且一个个上传,万一哪个上传失败了,后面就不需要上传了,直接报错. 之前ASI的网络库中是有同步请求的接口,所以很好处理,AFNetwork的网络库只有异步的网络请求,该怎么实现呢? 1.循环异步拼组 - (void)uploadFile:(NSArray *)imageArray atIndex:(NSInteger)index imagesCount:(NSInteger

  • iOS开发中Quartz2D控制圆形缩放和实现刷帧效果

    Quartz2D简要回顾 一.什么是Quartz2D Quartz 2D是⼀个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成PDF 截图\裁剪图片 自定义UI控件 二.Quartz2D在iOS开发中的价值 为了便于搭建美观的UI界面,iOS提供了UIKit框架,⾥⾯有各种各样的UI控件 UILabel:显⽰文字 UIImageView:显示图片 UIButton:同时显示图片和⽂

  • IOS开发中键盘输入屏幕上移的解决方法

    在IOS开法中经常会遇到键盘遮挡屏幕的事情(比如输入账号密码验证码等等),就使得原本都不大的屏幕直接占了一半甚至更多的位置,这倒无所谓,关键是挡住了下面的按钮.这样的话按钮的事件也就触发不了,最好的解决办法就是当输入这些信息的时候让整个屏幕上移一个键盘的位置,或者上移到指定的位置. 首先一般输入的话都用的是UITextField,所以要监听用户什么时候开始输入和什么时候结束输入,直接设置代理代理就行了,要遵受 UITextFieldDelegate协议. //遵循协议 @interface Vi

随机推荐