標籤:size void uila efault ios 原創 round demo patch
原創
定時器裡面有個runloop mode,一般定時器是運行在defaultmode上。但是如果滑動了這個頁面,主線程runloop會轉到UITrackingRunLoopMode中,這時候就不能處理定時器了,造成定時器失效,原因就是runroop mode的問題
NSDefaultRunLoopMode(kCFRunLoopDefaultMode):預設,空閑狀態
UITrackingRunLoopMode:ScrollView滑動時會切換到該Mode
UIInitializationRunLoopMode:run loop啟動時,會切換到該Mode
NSRunLoopCommonModes(kCFRunLoopCommonModes)
這裡提供了兩種解決辦法: 1. 把定時器添加到當前線程訊息迴圈中 並指定訊息迴圈的模式為NSRunLoopCommonModes(無論runloop運行在哪個mode,都能運行) 2. 切換到主線程上更新UI
// 步驟1. 把NSTimer放到子線程中,但是要注意:因為自線程的訊息迴圈預設不開啟,所以這裡還需要開啟一下子線程的訊息迴圈
// 步驟2. 切換到主線程上更新UI #import "ViewController.h"
@interface ViewController ()
@property(nonatomic,strong)UIScrollView *scrollView;
@property(nonatomic,strong)NSTimer *timer;
@property(nonatomic,strong)UILabel *label;
@property(nonatomic,assign)float times;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView = [[UIScrollView alloc]init];
self.scrollView.frame = self.view.frame;
self.scrollView.backgroundColor = [UIColor cyanColor];
self.scrollView.contentSize = CGSizeMake(375, 2000);
[self.view addSubview:self.scrollView];
self.label = [[UILabel alloc]init];
self.label.frame = CGRectMake(100, 100, 100, 100);
self.label.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.label];
_times = 0;
//self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(demo) userInfo:nil repeats:YES];
// 解決方案1: 把定時器添加到當前線程訊息迴圈中 並指定訊息迴圈的模式為
// cNSRunLoopCommonModes(無論runloop運行在哪個mode,都能運行)
// 加上這句完美解決
//[[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];
// 解決方案2:
// 1. 把NSTimer放到子線程中,但是要注意:因為自線程的訊息迴圈預設不開啟,所以這裡還需要開啟一下子線程的訊息迴圈
// 2. 切換到主線程上更新UI
dispatch_async(dispatch_get_global_queue(0, 0), ^{
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(demo) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
});
}
-(void)demo{
_times+=0.1;
//self.label.text = [NSString stringWithFormat:@"%f",_times];
// 隊列方式(在主線程上更新UI)
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.label.text = [NSString stringWithFormat:@"%f",_times];
}];
// GCD方式
/*dispatch_async(dispatch_get_main_queue(), ^{
self.label.text = [NSString stringWithFormat:@"%f",_times];
});*/
}
@end
iOS - scrollView與NSTimer的失效問題詳解