NSTimer可以在APP中设置定时执行的任务. 而使用setKeepAliveTimeout: handler:可以设置APP后台运行时的定时任务.
NSTimer
下边是NSTimer的头文件, 其中介绍了timerWithTimeInterval, scheduledTimerWithTimeInterval, initWithFireDate, fire, invalidate等方法.
使用fire方法可以立即触发定时器:
1. 在重复执行的定时任务中使用fire可以立即触发任务, 但不会中断其之前的定时计划.
2. 在一次性的定时任务中使用fire立即触发任务, 但该定时器立即失效.
invalidate方法是唯一一个可以将定时器从runloop中移除的方法.
/* NSTimer.h
Copyright (c) 1994-2014, Apple Inc. All rights reserved.
*/
#import <Foundation/NSObject.h>
#import <Foundation/NSDate.h>
@interface NSTimer : NSObject
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(id)ui repeats:(BOOL)rep NS_DESIGNATED_INITIALIZER;
- (void)fire;
@property (copy) NSDate *fireDate;
@property (readonly) NSTimeInterval timeInterval;
// Setting a tolerance for a timer allows it to fire later than the scheduled fire date, improving the ability of the system to optimize for increased power savings and responsiveness. The timer may fire at any time between its scheduled fire date and the scheduled fire date plus the tolerance. The timer will not fire before the scheduled fire date. For repeating timers, the next fire date is calculated from the original fire date regardless of tolerance applied at individual fire times, to avoid drift. The default value is zero, which means no additional tolerance is applied. The system reserves the right to apply a small amount of tolerance to certain timers regardless of the value of this property.
// As the user of the timer, you will have the best idea of what an appropriate tolerance for a timer may be. A general rule of thumb, though, is to set the tolerance to at least 10% of the interval, for a repeating timer. Even a small amount of tolerance will have a significant positive impact on the power usage of your application. The system may put a maximum value of the tolerance.
@property NSTimeInterval tolerance NS_AVAILABLE(10_9, 7_0);
- (void)invalidate;
@property (readonly, getter=isValid) BOOL valid;
@property (readonly, retain) id userInfo;
@end
使用实例
下边的使用实例要添加一个定时任务, 定时执行一个POST请求将设备电量信息汇报到指定的API.
const NSString *batteryLevelURL = @"http://localhost/batteryLevel/level";
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self reportDeviceInfo];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:100 target:self
selector:@selector(reportDeviceInfo) userInfo:nil repeats:true];
}
-(void) reportDeviceInfo {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:batteryLevelURL parameters:[self getDeviceInfo]
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"succeed in reporting device info.");
self.networkLabel.textColor = UIColor.blackColor;
self.networkLabel.text = @"Succeed in reporting this device info.";
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"fail to report device info.");
self.networkLabel.textColor = UIColor.redColor;
self.networkLabel.text = @"Fail to report device info. please check network.";
}];
}
其中, 使用了scheduledTimerWithTimeInterval设置定时执行的重复任务.
主要参数为间隔时间, 以及定时执行的函数selector:@selector(reportDeviceInfo).
后台定时执行
使用NSTimer的定时任务只能在前台执行, 一旦APP进入到后台, 该定时器即不能正常工作.
如果需要后台执行的定时任务的话, 需要做到两点:
1. 在Info.plist中添加UIBackgroundModes属性, 即Required background modes, 添加VOIP, audio, location, 蓝牙, download等.
2. 使用setKeepAliveTimeout: handler:方法来注册一个周期性执行的任务, 而不管是否运行在后台.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self reportDeviceInfo];
[[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{[self reportDeviceInfo];}];
}
此时, 如果该APP运行在后台, reportDeviceInfo()方法仍然会周期性地调用.
使用clearKeepAliveTimeout可以相应地清除该定时任务.
- (BOOL)setKeepAliveTimeout:(NSTimeInterval)timeout handler:(void(^)(void))keepAliveHandler NS_AVAILABLE_IOS(4_0);
- (void)clearKeepAliveTimeout NS_AVAILABLE_IOS(4_0);