定时器的应用

说到定时器,在项目中使用最多的可能就是NSTimer了,其实除了NSTimer,在iOS开发中,我们还有许多其他的方式可用来创建定时器。通过CADisplayLink或者GCD也可以是想强大的定时器功能。

缺点:

  1. NSTimer定时器,其实不是按时间间隔进行循环调用的,实际上在定时器注册到runloop中后runloop会设置一个一个的时间点进行调用,如果错过了,则定时器并不会延时条用,而是直接等待下一个时间点调用,所以台式不精准的。
  2. 子线程要手动开启RunLoop,这样创建的NSTimer才可以执行。
  3. NSTimer容易发生内存泄漏,并且一个应用程序中,如果激活多个定时器的话很消耗性能

中心化管理NSTimer定时器

创建一个Task类,将它作为定时器的任务类,使用继承于NSObject,在其中声明如下属性和方法:

//Task.h文件
@interface Task : NSObject
- (instancetype)initWithTimer:(NSUInteger)time handler: (void(^)(void)) hander;
//标志
@property (nonatomic, strong, readonly) NSString * taskID;
//时间单位为 1/60秒
@property (nonatomic, assign) NSUInteger timeI;//需要执行的动作
@property (nonatomic, copy)void(^event)(void);
@end//Task.m文件
#import "Task.h"@implementation Task- (instancetype)initWithTimer:(NSUInteger)time handler: (void(^)(void)) hander {self = [super init];if (self) {self.timeI = time;self.event = hander;_taskID = [NSUUID UUID].UUIDString;}return self;
}
@end

在创建一个TimerManager的类,使其继承于NSObject,这个类的作用是统一管理整个工程的定时任务,我们将其设计为单例,接口如下:

//TimerManager.h文件
@class Task;
@interface TimerManager : NSObject
//单例
+ (instancetype)shareManager;
//运行定时器任务
- (void)runTask:(Task *) task;
//取消定时器任务
- (void)cancelTaskWithID: (NSString *) taskID;
@end//TimerManager.m文件#import "TimerManager.h"
#import "Task.h"@interface TimerManager()@property (nonatomic, strong) NSMutableArray *taskArray;
@property (nonatomic, strong) NSTimer *timer;
@end@implementation TimerManager+ (instancetype)shareManager {static dispatch_once_t onceToken;static TimerManager *manager = nil;dispatch_once(&onceToken, ^{if (!manager) {manager = [[TimerManager alloc] init];}});return manager;
}- (instancetype)init
{self = [super init];if (self) {[[NSRunLoop mainRunLoop] addTimer:self.timer forMode: NSRunLoopCommonModes];}return self;
}- (void)runTask:(Task *)task {for (Task *t in self.taskArray) {if ([t.taskID isEqualToString:task.taskID]) {return;}}[self.taskArray addObject:task];
}- (void)cancelTaskWithID:(NSString *)taskID {for (int i = (int)self.taskArray.count - 1; i >= 0; i--) {if ([[self.taskArray[i] taskID] isEqualToString:taskID]) {[self.taskArray removeObjectAtIndex:i];}}
}- (NSMutableArray *)taskArray {if (!_taskArray) {_taskArray = [NSMutableArray array];}return _taskArray;
}- (NSTimer *)timer {if (!_timer) {static int index = 0;_timer = [NSTimer scheduledTimerWithTimeInterval:1 / 60 repeats:YES block:^(NSTimer * _Nonnull timer) {if (index == 59) {index = 0;}for (Task *t in self.taskArray) {if (index % t.timeI == 0) {t.event();}}index++;}];}return _timer;
}
@end

这样,当我们需要使用定时任务时,将任务加入此中管理单例即可,无论我们有多少个任务,整个工程都只有一个定时器运行。Demo如下

#import "ViewController.h"
#import "Task.h"
#import "TimerManager.h"
@interface ViewController ()
@property (nonatomic, copy) NSString *taskID;
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];Task *t1 = [[Task alloc] initWithTimer:60 handler:^{NSLog(@"DDDD");}];self.taskID = t1.taskID;Task *t2 = [[Task alloc] initWithTimer:30 handler:^{NSLog(@"DDDD2");}];[[TimerManager shareManager] runTask:t1];[[TimerManager shareManager] runTask:t2];NSLog(@"%@", t2.taskID);// Do any additional setup after loading the view.
}- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {NSLog(@"%@", self.taskID);[[TimerManager shareManager] cancelTaskWithID:self.taskID];//只关闭了task1
}
@end

CADisplayLink

它也是一种定时器,并且在很多自定义动画中,CADisplayLink有这比NSTimer更好地表现,CADisplayLink调用频率和设备的刷新频率一致。
由于CADisplayLink这个特性我们可以用来检测应用程序的帧率。

self.link = [CADisplayLink displayLinkWithTarget:self selector:@selector(myDisplayLink)];[self.link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];- (void) myDisplayLink {static NSTimeInterval curr = 0;if (curr != 0) {NSLog(@"%f", 1 /(self.link.timestamp - curr));}curr = self.link.timestamp;
}

注意它和NSTimer一样,当我们不再需要使用CADisplayLink定时器的死后我们需要手动设置其失效方法如下

- (void)invalidate;

GCD

熟悉GCD的开发者会经常使用下面的法法来处理延迟任务:

//延迟0.5秒执行不受RunLoop影响
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{//        code to be executed after a specified delay});

GCD定时器

//
//  ViewController.m
//  CenterManagerTimer
//
//  Created by bruceyao on 2021/3/30.
//#import "ViewController.h"@interface ViewController ()@property (nonatomic, strong) dispatch_source_t timer;
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
//    设置频率dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, 0), 1 * NSEC_PER_SEC, 0);dispatch_source_set_event_handler(self.timer, ^{NSLog(@"Hello");});
//    激活dispatch_resume(self.timer);
}- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {NSLog(@"%@", self.taskID);[[TimerManager shareManager] cancelTaskWithID:self.taskID];
}- (void) myDisplayLink {static NSTimeInterval curr = 0;if (curr != 0) {NSLog(@"%f", 1 /(self.link.timestamp - curr));}curr = self.link.timestamp;
}
@end

iOS 优化之NSTimer相关推荐

  1. iOS中关于NSTimer使用知多少

    看到这个标题,你可能会想NSTimer不就是计时器吗,谁不会用,不就是一个能够定时的完成任务的东西吗? 我想说你知道NSTimer会retain你添加调用方法的对象吗?你知道NSTimer是要加到ru ...

  2. 如何查看经过iOS优化的PNG图片

    编译iOS应用是,xcode会对PNG文件进行优化,这样图片预览就无法显示.那么如何查看这些经过优化的文件呢? 优化的动作是由pngcrush 工具完成的,你可以再xcode中找到.pngcrush  ...

  3. iOS 优化 - 瘦身

    前言 iOS 优化将是一个专题,其中会包括包体积优化(瘦身).启动时间优化.UI 优化等等.那么这个专题的开篇就从瘦身开始吧. APP 的大小是分为 APP 下载大小和安装大小两个概念的. 下载大小是 ...

  4. [iOS] 使用 blockable NSTimer 避免内存泄漏

    背景 此知识点,从阅读<Effective Objective-C>中学习到,现扩展到 Swift 并兼容 iOS 10+ NSTimer 提供定时执行任务的功能,可用于延时或者重复处理事 ...

  5. iOS 优化资源文件

    资源文件是放置在应用程序本地与应用程序一起变异.打包和发布的非程序代码文件,如应用中的声音.视频.图片和文本文件等. 1.图片文件优化 图片文件优化包括文件格式和文件大小的优化.移动设备中,支持的图片 ...

  6. iOS中定时器NSTimer的开启与关闭

    调用一次计时器方法: [cpp] view plain copy   myTimer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:self ...

  7. iOS中定时器NSTimer的使用

    1.初始化 + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelect ...

  8. iOS优化内存,提升性能 之五

    Advanced Autorelease Pool 高级自动释放池 在之前的章节你已经学习了很多基本的内存方面的知识.这个部分将会涉及到使用自动释放的高级技术,同时展示你应该在哪里使用,从而在受限的情 ...

  9. IOS中定时器NSTimer

    调用一次计时器方法: [cpp]  view plain copy   myTimer = [NSTimer scheduledTimerWithTimeInterval:1.5 target:sel ...

最新文章

  1. 判断两棵树是否相等与使用二叉链表法建立二叉搜索树
  2. 未来智能实验室成立,建设世界第一个智能系统智商评测和趋势研究机构
  3. spring_Spring MVC控制器的单元测试:配置
  4. 5、员工上班时间的问题 - CEO之公司管理经验谈
  5. “问答官”活动SQL专场来啦!小米行李箱、无线鼠标等你拿!
  6. ASP.NET MVC与RAILS3的比较
  7. Linux的实际操作:时间日期类的实用指令(date cal)
  8. python查看内存地址的内容_python中如何查看指定内存地址的内容
  9. Java中System.nanoTime()的使用
  10. 简述tcp协议的可靠性有哪些机制_腾讯面试HTTP与TCP/IP20连问,你能答出多少?
  11. Atitit 局部图查找大图 方法 与 说明
  12. 傻瓜式一键破解MD5加密
  13. 一款真正可以操作的数据中心可视化管理软件
  14. nested exception is java.lang.NumberFormatException: For input string: NaN
  15. (10.1.3.4)UI设计,扁平化还是拟物化?
  16. 生成自己的自签名证书
  17. 记一次逗逼的codecraft算法大赛的参赛经历
  18. 这是我见过的最垃圾的代码,没有之一
  19. 赛事解读|中国工程机器人大赛暨国际公开赛——飞思实验室空中机器人项目-仿真与自主任务赛项
  20. “健康码”背后的腾讯C2B大练兵

热门文章

  1. 基于商密SM9算法的物联网安全平台设计与应用
  2. 《团长》引发收视恶战 四大卫视疯狂打擂
  3. 《玛丽莲·梦露》我不止性感,还有从底层溯流而上的努力
  4. 内存管理API之page_address
  5. Evil Coordinate
  6. 联发科基带或打入苹果iPad供应链,久旱逢甘霖
  7. oppo r11 android版本,oppo r11 plus有哪些版本_oppo r11 plus内存多大-太平洋IT百科
  8. 全志R11_tinav2.5_TRecorder接口说明
  9. 探探提醒对方账号异常_探探显示对方账号异常
  10. 转载iphone开发学习笔记