版本记录
版本号 | 时间 |
---|---|
V1.0 | 2017.05.01 |
前言
很多时候我们需要进行延迟处理,在ios中延迟方法有很多,下面就介绍几种主要的延时方法,各有优缺点,希望大家能比较使用。
详情
一、perform selector方法
ios中关于这个方法有几个方法,主要如下:
@interface NSObject (NSDelayedPerforming)
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSRunLoopMode> *)modes;
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(nullable id)anArgument;
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;
@end
这个方法有个优点就是不会阻塞线程。此方式要求必须在主线程中执行,否则无效,没有取消的方法。我们就以第二个方法进行举例吧。
1. JJDelayMethodVC.m
#import "JJDelayMethodVC.h"
@interface JJDelayMethodVC ()
@end
@implementation JJDelayMethodVC
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
//第一种延时函数
[self delayMethodOne];
}
#pragma mark - Object Private Function
- (void)delayMethodOne
{
NSDate *dateBefore = [NSDate date];
NSLog(@"dateBefore---%@",dateBefore);
[self performSelector:@selector(delayMethodOneAction) withObject:nil afterDelay:2];
}
#pragma mark - Action
- (void)delayMethodOneAction
{
NSDate *dateAfter = [NSDate date];
NSLog(@"dateAfter---%@",dateAfter);
}
@end
我们看输出。
2017-05-01 22:35:37.231 delayMethod[6783:293524] dateBefore---2017-05-01 14:35:37 +0000
2017-05-01 22:35:39.302 delayMethod[6783:293524] dateAfter---2017-05-01 14:35:39 +0000
可以看见确实延时了2s。上面这个方法的object可以传参,然后在执行selector的方法中进行接收并处理。
二、GCD dispatch_after方法
GCD中dispatch_after方法也可以实现延迟。而且不会阻塞线程,效率较高(推荐使用),并且可以在参数中选择执行的线程,同样没有可取消的方法。
#import "JJDelayMethodVC.h"
@interface JJDelayMethodVC ()
@end
@implementation JJDelayMethodVC
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
//第一种延时函数
// [self delayMethodOne];
//第二种延时函数 GCD dispatch
[self delayByDispatch];
}
#pragma mark - Object Private Function
- (void)delayByDispatch
{
NSDate *dateBefore = [NSDate date];
NSLog(@"dateBefore---%@",dateBefore);
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC));
dispatch_after(time, dispatch_get_main_queue(), ^{
NSDate *dateAfter = [NSDate date];
NSLog(@"dateAfter---%@",dateAfter);
});
}
@end
我们看输出结果。
2017-05-01 22:53:14.991 delayMethod[6980:303434] dateBefore---2017-05-01 14:53:14 +0000
2017-05-01 22:53:17.992 delayMethod[6980:303434] dateAfter---2017-05-01 14:53:17 +0000
三、UIView动画实现延时
我们都知道UIView可以实现动画延迟,延时操作写在block里面,这里需要说明的是,block中的代码对于是支持animation的代码,才会有延迟效果,对于不支持animation的代码不会有延迟效果。
下面我们看代码。
#import "JJDelayMethodVC.h"
@interface JJDelayMethodVC ()
@property (nonatomic, strong) UILabel *titleLabel;
@end
@implementation JJDelayMethodVC
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 100)];
titleLabel.backgroundColor = [UIColor orangeColor];
[self.view addSubview:titleLabel];
self.titleLabel = titleLabel;
self.view.backgroundColor = [UIColor lightGrayColor];
//第一种延时函数
// [self delayMethodOne];
//第二种延时函数 GCD dispatch
// [self delayByDispatch];
//UIView实现延迟
[self delayByAnimation];
}
#pragma mark - Object Private Function
- (void)delayByAnimation
{
NSDate *dateBefore = [NSDate date];
NSLog(@"dateBefore---%@",dateBefore);
[UIView animateKeyframesWithDuration:0.25 delay:5 options:UIViewKeyframeAnimationOptionLayoutSubviews animations:^{
self.titleLabel.transform = CGAffineTransformMakeTranslation(0, 300);
} completion:^(BOOL finished) {
NSDate *dateAfter = [NSDate date];
NSLog(@"dateAfter---%@",dateAfter);
self.titleLabel.transform = CGAffineTransformIdentity;
}];
}
@end
然后我们看输出和gif图。
2017-05-01 23:08:39.491 delayMethod[7238:313886] dateBefore---2017-05-01 15:08:39 +0000
2017-05-01 23:08:44.816 delayMethod[7238:313886] dateAfter---2017-05-01 15:08:44 +0000
需要说明的是,UIview动画延迟是不会阻塞线程的。
四、NSThread sleep方法
这个方法也可以实现延时,其实就是让该线程睡眠一段时间,所以它一定会阻塞线程,浪费资源,所以一般是不推荐使用的。它没有取消的方法,可以放在主线程或者子线程中,如果一定要用还是建议放在子线程中防止卡顿界面。
#import "JJDelayMethodVC.h"
@interface JJDelayMethodVC ()
@property (nonatomic, strong) UILabel *titleLabel;
@end
@implementation JJDelayMethodVC
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 100)];
titleLabel.backgroundColor = [UIColor orangeColor];
[self.view addSubview:titleLabel];
self.titleLabel = titleLabel;
self.view.backgroundColor = [UIColor lightGrayColor];
//第一种延时函数
// [self delayMethodOne];
//第二种延时函数 GCD dispatch
// [self delayByDispatch];
//UIView实现延迟
// [self delayByAnimation];
//第四种 thread sleep方法
[self delayByThreadSleep];
}
#pragma mark - Object Private Function
- (void)delayByThreadSleep
{
NSLog(@"%@",[NSThread currentThread]);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSDate *dateBefore = [NSDate date];
NSLog(@"dateBefore---%@",dateBefore);
[NSThread sleepForTimeInterval:3];
NSDate *dateAfter = [NSDate date];
NSLog(@"dateAfter---%@",dateAfter);
NSLog(@"%@",[NSThread currentThread]);
});
}
@end
看输出结果。
2017-05-01 23:44:20.307 delayMethod[7589:330545] <NSThread: 0x60800007a340>{number = 1, name = main}
2017-05-01 23:44:20.356 delayMethod[7589:330647] dateBefore---2017-05-01 15:44:20 +0000
2017-05-01 23:44:23.432 delayMethod[7589:330647] dateAfter---2017-05-01 15:44:23 +0000
2017-05-01 23:44:23.432 delayMethod[7589:330647] <NSThread: 0x600000264e80>{number = 3, name = (null)}
五、NSTime 定时器方法
定时器NSTimer也可以实现延迟,是一种非阻塞的执行方式。取消的话可以先判断isInvalidate然后调用invalidate取消该定时器。
我们先看代码。
#import "JJDelayMethodVC.h"
@interface JJDelayMethodVC ()
@property (nonatomic, strong) UILabel *titleLabel;
@end
@implementation JJDelayMethodVC
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 100)];
titleLabel.backgroundColor = [UIColor orangeColor];
[self.view addSubview:titleLabel];
self.titleLabel = titleLabel;
self.view.backgroundColor = [UIColor lightGrayColor];
//第一种延时函数
// [self delayMethodOne];
//第二种延时函数 GCD dispatch
// [self delayByDispatch];
//UIView实现延迟
// [self delayByAnimation];
//第四种 thread sleep方法
// [self delayByThreadSleep];
//第五种 timer方法
[self delayByTimer];
}
#pragma mark - Object Private Function
- (void)delayByTimer
{
NSDate *dateBefore = [NSDate date];
NSLog(@"dateBefore---%@",dateBefore);
NSLog(@"%@",[NSThread currentThread]);
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(delayByTimerAction) userInfo:nil repeats:NO];
}
- (void)delayByTimerAction
{
NSDate *dateAfter = [NSDate date];
NSLog(@"dateAfter---%@",dateAfter);
NSLog(@"%@",[NSThread currentThread]);
}
@end
然后我们看输出结果。
2017-05-01 23:53:38.677 delayMethod[7704:335921] dateBefore---2017-05-01 15:53:38 +0000
2017-05-01 23:53:38.677 delayMethod[7704:335921] <NSThread: 0x60800006ea00>{number = 1, name = main}
2017-05-01 23:53:41.752 delayMethod[7704:335921] dateAfter---2017-05-01 15:53:41 +0000
2017-05-01 23:53:41.753 delayMethod[7704:335921] <NSThread: 0x60800006ea00>{number = 1, name = main}
我这里没有取消timer,大家可以自己加上。
后记
时间就这么多了,先写这么多吧,以后有更好的东西在和大家分享。谢谢大家,晚安。