一、NSTimer
创建方式
a.这种方式创建的定时器,在哪个县城中创建加到哪个线程
_timer= [NSTimer scheduledTimerWithTimeInterval:1target:selfselector:@selector(changed) userInfo:nil repeats:YES];
b.该方法创建的NSTimer需要手动添加到RunLoop中
_timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(chagned) userInfo:nil repeats:YES];
注:若不加入到主线程中,定时器是不会启动的
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
注意:
a.当在一个控制器中Push到下个界面,而下一个界面有NSTimer定时器时,是会有内存泄漏的,所有务必要进行销毁,通常的做法是在- (void)viewDidDisappear:(BOOL)animated
是销毁定时器
通过dealloc即可以发现有没有销毁
b.当NSTimer 加入到了滚动视图上,当滚动视图的时候,可能会出现定时器不走的情况,典型的就是tabview中cell嵌套了Scrollview 即广告栏,当在滚动tabview时,广告栏图片不自动进行轮播了,处理方法如下:
b.1 将定时器加入到CurrentRunLoop中的CommonModel或者TrackingModel
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:UITrackingRunLoopMode];
b.2利用线程的方式解决NSTime不执行的问题
开一个线程
[NSThread detachNewThreadSelector:@selector(thread) toTarget:selfwithObject:nil];
在线程的响应方法中执行
- (void)thread
{
_timer= [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(chagned) userInfo:nil repeats:YES];
//让子线程的RunLoop开启
[[NSRunLoopcurrent RunLoop] run];
}
//RunLoop的三种模式
// NSDefaultRunLoopMode默认
// NSRunLoopCommonModes通用模式
// UITrackingRunLoopMode UI事件传入模式(用户的点击,拖动等)
定时器的相关方法
a.暂停定时器
[_timer setFireDate:[NSDate distantFuture]];
b.开始定时器
[_timersetFireDate:[NSDate distantPast]];
c.销毁定时器
[_timer invalidate];
_timer=nil;// 一般是一起用(_timer = nil)
二、CADisplayLink
CADisplayLink 同屏幕的刷新率,一般屏幕的默认刷新次数为60/s
使用方式
_displayLink = [CADisplayLink displayLinkWithTarget:selfselector:@selector(update)];
//修改刷新频率,多少帧刷新一次
_displayLink.frameInterval =60;
//销毁
// [_displayLink invalidate];
// _displayLink = nil;
//当添加到RunLoop中会立即执行
[_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
是否 暂停定时器
_displayLink.paused=YES;
三、GCD的方式
__blockintj =0;
//第三种创建方式:
timer=dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0,0,dispatch_get_main_queue());
// intervarlInSeconds每隔多久执行一次
// leewayInSeconds允许出现多少误差,0为最精准
dispatch_source_set_timer(timer,DISPATCH_TIME_NOW,1*NSEC_PER_SEC,0*NSEC_PER_SEC);
//执行的事件
dispatch_source_set_event_handler(timer, ^{
NSLog(@"%d", j++);
});
//执行
dispatch_resume(timer);
//停止
// dispatch_source_cancel(timer);
Run loop是和线程紧密相关的非常重要的基础。一个Run loop就是一个事件处理循环,可用于调度,协调输入事件的接收。Run loop是自动管理的。他的作用就是循环、处理事件。
runloop基本作用
1.保持程序的持续运行
2.处理app的各种事件(比如触摸事件,定时器事件,selector事件)
3.节省CPU资源,提高程序性能。
RunLoop的用处
1.解决NSTimer滑动视图时,定时器暂停的问题
2.解决单滑动ScrollView时NSURLConnection代理不执行的问题
eg:下载数据时滑动滚动视图进度条不走,不滑动时,有继续走
解决方案
a.将方法NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];换成
NSURLConnection*connection = [[NSURLConnectionalloc]initWithRequest:requestdelegate:selfstartImmediately:NO];// 注:这里的是否立即执行应该选择NO,否则,下面就没办法马上添加到CommonModel中了
b.将connection添加到NSRunLoopCommonModes模式下
[connectionscheduleInRunLoop:[NSRunLoopcurrentRunLoop]forMode:NSRunLoopCommonModes];
[connectionstart]; //开始连接
完整代码如下
@interfaceViewController()
//解决当滑动ScrollView时NSURLConnection代理不执行的问题
NSURL*url = [NSURLURLWithString:@"http://dl_dir.qq.com/qqfile/qq/QQforMac/QQ_V2.4.1.dmg"];
NSURLRequest*request = [NSURLRequestrequestWithURL:url];
// NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
NSURLConnection*connection = [[NSURLConnectionalloc]initWithRequest:requestdelegate:selfstartImmediately:NO];
//将connection添加到RunLoop中,并设置模式
[connectionscheduleInRunLoop:[NSRunLoopcurrentRunLoop]forMode:NSRunLoopCommonModes];
[connectionstart];
#pragma mark - NSURLConnectionDataDelegate
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
NSLog(@"%ld", data.length);
}
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
NSLog(@"下载完成!");
}