版本記錄
| 版本號 | 時間 |
|---|---|
| V1.0 | 2017.05.01 |
前言
很多時候我們需要進行延遲處理,在ios中延遲方法有很多,下面就介紹幾種主要的延時方法,各有優(yōu)缺點,希望大家能比較使用。
詳情
一、perform selector方法
ios中關(guān)于這個方法有幾個方法,主要如下:
@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
這個方法有個優(yōu)點就是不會阻塞線程。此方式要求必須在主線程中執(zhí)行,否則無效,沒有取消的方法。我們就以第二個方法進行舉例吧。
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];
//第一種延時函數(shù)
[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可以傳參,然后在執(zhí)行selector的方法中進行接收并處理。
二、GCD dispatch_after方法
GCD中dispatch_after方法也可以實現(xiàn)延遲。而且不會阻塞線程,效率較高(推薦使用),并且可以在參數(shù)中選擇執(zhí)行的線程,同樣沒有可取消的方法。
#import "JJDelayMethodVC.h"
@interface JJDelayMethodVC ()
@end
@implementation JJDelayMethodVC
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
//第一種延時函數(shù)
// [self delayMethodOne];
//第二種延時函數(shù) 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
我們看輸出結(jié)果。
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動畫實現(xiàn)延時
??我們都知道UIView可以實現(xiàn)動畫延遲,延時操作寫在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];
//第一種延時函數(shù)
// [self delayMethodOne];
//第二種延時函數(shù) GCD dispatch
// [self delayByDispatch];
//UIView實現(xiàn)延遲
[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方法
??這個方法也可以實現(xiàn)延時,其實就是讓該線程睡眠一段時間,所以它一定會阻塞線程,浪費資源,所以一般是不推薦使用的。它沒有取消的方法,可以放在主線程或者子線程中,如果一定要用還是建議放在子線程中防止卡頓界面。
#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];
//第一種延時函數(shù)
// [self delayMethodOne];
//第二種延時函數(shù) GCD dispatch
// [self delayByDispatch];
//UIView實現(xiàn)延遲
// [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
看輸出結(jié)果。
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也可以實現(xiàn)延遲,是一種非阻塞的執(zhí)行方式。取消的話可以先判斷isInvalidate然后調(diào)用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];
//第一種延時函數(shù)
// [self delayMethodOne];
//第二種延時函數(shù) GCD dispatch
// [self delayByDispatch];
//UIView實現(xiàn)延遲
// [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
然后我們看輸出結(jié)果。
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,大家可以自己加上。
后記
??時間就這么多了,先寫這么多吧,以后有更好的東西在和大家分享。謝謝大家,晚安。
