iOS:延时执行的三种方式

延时执行的三种方式:performSelectorXXX方法、GCD中延时函数、创建定时器

第一种方式:NSObject分类当中的方法,延迟一段时间调用某一个方法

@interface NSObject (NSDelayedPerforming)

※延时调用在当前线程使用特定模式的方法(如果数组没有数据或者参数为nil,则不会调用selector中方法)

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;

※延时调用在当前线程使用默认模式的方法

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;

※取消某一个延时调用请求

+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(id)anArgument;

※取消全部的延时调用请求

+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;

@end

-============================================================================

第二种方式:GCD当中的方法

间隔时间宏定义:NSEC纳秒、MSEC毫秒、 USEC微妙、 SEC秒、 PER每

#define NSEC_PER_SEC                     //每一秒有多少纳秒

#define NSEC_PER_MSEC                  //每一毫秒有多少纳秒

#define USEC_PER_SEC                    //每一秒有多少微妙(注意:在纳秒的基础上)

#define NSEC_PER_USEC                     //每一微秒有多少纳秒

开始时间宏定义:

#define DISPATCH_TIME_NOW            //当前时间

#define DISPATCH_TIME_FOREVER        //永久时间(无限循环)

相关方法:

※时间变量类型

typedef uint64_t dispatch_time_t;

※创建延时间隔时间(参数:宏定义开始时间、设置秒数*宏定义的间隔时间)

dispatch_time(dispatch_time_t when, int64_t delta);

※队列变量类型(主队列、默认全局队列、自定义队列)

dispatch_queue_t  queue

※执行延时函数操作(参数:延迟时间、队列、block操作)

dispatch_after(dispatch_time_t when,dispatch_queue_t  queue,dispatch_block_t block);

===================================================================================

第三种方式:创建定时器

@interface NSTimer : NSObject

属性:

※设置定时器的启动时间,管理定时器的启动和停止

@property (copy) NSDate *fireDate;

※只读属性,获取时间间隔

@property (readonly) NSTimeInterval timeInterval;

※这是7.0之后的一个新特性,由于NSTimer不精确,通过它设置误差范围

@property NSTimeInterval tolerance ;

※只读属性,获取定时器是否有效

@property (readonly, getter=isValid) BOOL valid;

※参数信息

@property (readonly, retain) id userInfo;

方法:

※创建定时器的time-类方法,需要手动fire开启定时器,将执行方法封装到NSInvocation中

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;

※创建定时器的time-类方法,需要手动fire开启定时器

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;

※创建定时器的scheduled-类方法,不需要手动fire开启定时器,将执行方法封装到NSInvocation中

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;

※创建定时器的scheduled-类方法,不需要手动fire开启定时器

+ (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;

※开启定时器

- (void)fire;

※使定时器失效,将定时器从循环池移除掉

- (void)invalidate;

@end

??创建定时器中类方法拓展:由于用到NSInvocation对象,所以涉及到两个类NSInvocation和NSMethodSignature签名类、还有一个执行线程类NSRunLoop

??(1)NSInvocation : NSObject

用到的属性:

@property (assign) id target;   //设置执行目标

@property SEL selector;         //设置执行方法

用到的方法:

+ (NSInvocation *)invocationWithMethodSignature:(NSMethodSignature *)sig;  //创建NSInvocation对象

??(2)NSMethodSignature : NSObject

方法:

(下面两个方法均继承自NSObject):必须是用当前要执行的方法所在的类或类对象来调用下面的类方法或实例方法创建签名对象

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;    //创建方法签名对象的实例方法(当前要执行的方法所在类对象来调用)

+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector; //创建方法签名对象的类方法(必须是当前要执行的方法所在的类来调用)

??(3)NSRunLoop:NSObject

用到的方法:

+ (NSRunLoop *)currentRunLoop;       //获取当前运行线程

+ (NSRunLoop *)mainRunLoop;           //获取主运行线程

- (void)addTimer:(NSTimer *)timer forMode:(NSString *)mode;            //将定时器添加到运行线程中

用到的参数模式mode:

FOUNDATION_EXPORT NSString * const NSDefaultRunLoopMode;      //默认执行模式

FOUNDATION_EXPORT NSString * const NSRunLoopCommonModes    //公共执行模式

注意:这五种初始化方法的异同:

1、参数repeats是指定是否循环执行,YES将循环,NO将只执行一次。

2、timerWithTimeInterval这两个类方法创建出来的对象如果不用 addTimer: forMode方法手动加入主循环池中,将不会循环执行。如果将定时器加到了主循环池中,则不需要手动调用fire启动定时器;相反,如果没有将定时器加到主循环池中,则需要手动调用fire,此时定时器会启动执行一次。

3、scheduledTimerWithTimeInterval这两个方法不需要手动调用fire,会自动执行,并且自动加入主循环池。

4、init方法需要手动加入循环池,它会在设定的启动时间启动。

例如加入循环池:

[[NSRunLoop mainRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];

启动定时器:

[timer fire];

=================================================================================

具体举例如下:

第一种方式:用NSObject的performSelectorXXX方法进行延迟调用。

1.创建延时请求

[self performSelector:@selector(printString:) withObject:@"hello world" afterDelay:3.0];

2.创建被调用的函数

-(void)printString:(NSString *)str
{
    NSLog(@"%@",str);
}

运行结果如下:

2015-10-07 20:27:40.938 03-performSelector-delay[2968:222584] hello world

第二种方式:用GCD中的dispatch_after方法进行延迟调用。

1.创建延时请求

//创建延迟时间,从当前时间开始,3秒后执行。 3秒需要转化为纳秒,因为该函数是以纳秒为基础进行的dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, 3.0*NSEC_PER_SEC);//执行延迟函数
dispatch_after(delay, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self printString:@"hello world"];
    });

2.创建被调用的函数

-(void)printString:(NSString *)str
{
    NSLog(@"%@",str);
}

运行结果如下:

2015-10-07 20:27:40.940 03-GCD-delay[2968:222584] hello world

第三种方式:使用定时器NSTimer进行延迟调用

3.1采用第一个类方法,循环延迟调用(此方法不需要手动调用fire启动定时器,也不需要将定时器加入到循环池才能重复执行)

//类方法创建定时器[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(printString:)userInfo:nil repeats:YES];
//执行的方法
-(void)printString:(NSTimer *) timer
{
    NSLog(@"hello world");
}

运行结果:我只粘贴出执行4次的结果,,,,

2015-10-07 20:27:40.938 03-延迟调用-delay[2968:222584] hello world
2015-10-07 20:27:40.940 03-延迟调用-delay[2968:222584] hello world
2015-10-07 20:27:40.940 03-延迟调用-delay[2968:222584] hello world
2015-10-07 20:27:41.226 03-延迟调用-delay[2968:222719] hello world

3.2采用第二个类方法:(分循环执行和只执行一次的情况,演示如下)

《1》循环延迟调用(把定时器加入到循环池中,此时不需要手动调用fire启动定时器,定时器能重复执行)

//类方法创建定时器NSTimer *timer = [NSTimer timerWithTimeInterval:3.0 target:self selector:@selector(printString:) userInfo:nil repeats:YES];

//将定时器加到循环池中
[[NSRunLoop currentRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];
//执行的方法
-(void)printString:(NSTimer *) timer
{
    NSLog(@"hello world");
}

运行结果:我只粘贴出执行4次的结果,,,,

2015-10-07 20:27:40.938 03-延迟调用2-delay[2968:222584] hello world
2015-10-07 20:27:40.940 03-延迟调用2-delay[2968:222584] hello world
2015-10-07 20:27:40.940 03-延迟调用2-delay[2968:222584] hello world
2015-10-07 20:27:41.226 03-延迟调用2-delay[2968:222719] hello world

《2》只调用一次,没有把定时器加入到循环池,需要手动调用fire来启动定时器

//类方法创建定时器NSTimer *timer = [NSTimer timerWithTimeInterval:3.0 target:self selector:@selector(printString:) userInfo:nil repeats:NO];

//启动定时器
[timer fire];   

//定时器失效
//[timer invalidate];

//执行的方法

-(void)printString:(NSTimer *) timer
{
    NSLog(@"hello world");
}

运行结果如下:只有一个输出

2015-10-07 21:12:54.031 03-延迟执行3-delay[3176:239321] hello world

3.3采用第三个类方法循环调用延迟函数:需要创建签名对象和NSInvocation对象,来设置目标和执行方法,此方法不需要手动启动定时器和加入循环池

//创建签名类标识对象(用当前要执行的方法和它所在的类做签名)
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:@selector(printString)];

//创建NSInvocation实例
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];

//设置目标和执行方法
[invocation setTarget:self];
[invocation setSelector:@selector(printString)];

//类方法创建定时器
[NSTimer scheduledTimerWithTimeInterval:3.0 invocation:invocation repeats:YES];
//执行方法
-(void)printString
{
    NSLog(@"hello world");
}

运行结果:我只粘贴出执行4次的结果,,,,

2015-10-07 21:35:15.429 03-延迟执行4-delay[3258:247360] hello world
2015-10-07 21:35:18.428 03-延迟执行4-delay[3258:247360] hello world
2015-10-07 21:35:21.429 03-延迟执行4-delay[3258:247360] hello world
2015-10-07 21:35:24.428 03-延迟执行4-delay[3258:247360] hello world

3.4采用实例方法进行循环延迟调用:循环延迟调用(把定时器手动加入到循环池中,定时器能重复执行)

//创建首次启动时间
NSDate *date = [NSDate distantPast]; //过去某个时间(可以自定义)

//创建定时器
NSTimer *timer = [[NSTimer alloc]initWithFireDate:date interval:3.0 target:self selector:@selector(printString) userInfo:nil repeats:YES];

//把定时器加到循环池
[[NSRunLoop currentRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];

//执行的方法
-(void)printString
{
    NSLog(@"hello world");
}

运行结果:我只粘贴出执行4次的结果,,,,

2015-10-07 22:22:35.373 03-延迟执行5-delay[3429:266949] hello world
2015-10-07 22:22:38.326 03-延迟执行5-delay[3429:266949] hello world
2015-10-07 22:22:41.326 03-延迟执行5-delay[3429:266949] hello world
2015-10-07 22:22:44.326 03-延迟执行5-delay[3429:266949] hello world

还有其他没演示的方法,差不多一样,就不一一演示了。

时间: 2024-10-14 03:08:50

iOS:延时执行的三种方式的相关文章

iOS延时执行的三种方法

@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css); @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css); 1. NSTimer,可以设置

延时执行的三种方式

1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 // Do any additional setup after loading the view, typically from a nib. 5 } 6 7 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 8 { 9 NSLog(@"-----touchesBegan1-----"); 10 11 1

IOS中延时执行的几种方式的比较和汇总

本文列举了四种延时执行某函数的方法及其一些区别.假如延时1秒时间执行下面的方法. - (void)delayMethod { NSLog(@"execute"); } 1.performSelector方法 [self performSelector:@selector(delayMethod) withObject:nil afterDelay:1.0f]; 此方式要求必须在主线程中执行,否则无效.是一种非阻塞的执行方式,暂时未找到取消执行的方法. 2.定时器:NSTimer [NS

【iOS开发系列】延时执行的几种方式

/* 本文列举了四种延时执行某函数的方法及其一些区别.假如延时1秒时间执行下面的方法. */ - (void)delayMethod { NSLog(@"execute"); } /** * [1].performSelector方法 */ [self performSelector:@selector(delayMethod) withObject:nil afterDelay:1.0f]; // 此方式要求必须在主线程中执行,否则无效. // 是一种非阻塞的执行方式, // 暂时未

iOS常见的延时执行有2种方式

调用NSObject的方法 [self performSelector:@selector(run) withObject:nil afterDelay:2.0]; // 2秒后再调用self的run方法 使用GCD函数 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 2秒后异步执行这里的代码... });

iOS 正则表达式使用的三种方式&语法

一.正则表达式定义 正则表达式:又称规则表达式(英语:Regular Expression,在代码中常简写为regex.regexp或RE,是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑. 二.特点 灵活性.逻辑性和功能性非常的强 可以迅速地用极简单的方式达到字符串的复杂控制 对于刚接触的人来说,比较晦涩难懂. 三.基本语法 选择 | 竖直分隔符代表选择.例

PHP定时执行的三种方式实现

1.windows 的计划任务2.linux的脚本程序3.让web浏览器定时刷新 具体实现 1.windows计划任务 PHP很少在win服务器上跑,具体实现也不再深究,看网上实现的原理大概是写bat脚本,然后让window任务添加执行这个bat脚本: 在网上找了些WINDOWS执行PHP的计划任务的方法,有一个写得很全,可惜在我这竟然没通过.最后不得不综合各门派的方法,才能在我这运行成功. 1.写一个PHP程序,命名为test.php,内容如下所示: <? $fp = fopen("te

iOS 拨打电话的三种方式总结

1,这种方法,拨打完电话回不到原来的应用,会停留在通讯录里,而且是直接拨打,不弹出提示,且苹果现在禁止不通过用户同意就拨打电话的应用上传 NSMutableString * str=[[NSMutableString alloc] initWithFormat:@"tel:%@",@"186xxxx6979"]; // NSLog(@"str======%@",str); [[UIApplication sharedApplication] op

iOS拨打电话的三种方式

1,这种方法,拨打完电话回不到原来的应用,会停留在通讯录里,而且是直接拨打,不弹出提示 var string = "tel:" + "136XXXXXXXX" UIApplication.sharedApplication().openURL(NSURL(string: string)!) 2,这种方法,打完电话后还会回到原来的程序,也会弹出提示,推荐这种 var string = "tel:" + "136XXXXXXXX"