解决iOS程序UI主线程和定时器相互阻塞的问题

我的问题是这样,我的页面上有一个UIScrollView和一个定时器用来记录当前考试模式下的剩余时间,问题出现了:当我滑动滚动试图时,定时器的方法便不在运行(即被UI主线程阻塞)。google一下找到了解决办法:将定时器放在非主线程中执行将更新UI的操作放到主线程,这样UI主线程和定时器就能互不干扰的相互工作了。

在另一个项目中,还解决了一个问题:手机验证码,获取按钮,点击获取后,会开始倒计时一段时间,按钮不可点,按钮上的文字不断变化。

获取验证码
120秒后重新获取
119秒后重新获取

以下是主要代码:

  1 #import "CountdownTool.h"
  2
  3 @interface CountdownTool()
  4 {
  5     UILabel *_lblShow;
  6     NSTimer *_timer;
  7 }
  8 @property (nonatomic, assign) NSInteger hour;
  9 @property (nonatomic, assign) NSInteger minute;
 10 @property (nonatomic, assign) NSInteger second;
 11 @property (nonatomic, copy) NSString  *strHour;
 12 @property (nonatomic, copy) NSString  *strMinute;
 13 @property (nonatomic, copy) NSString  *strSecond;
 14 @property (nonatomic, assign) NSInteger totalSeconds;
 15 @end
 16 @implementation CountdownTool
 17 @synthesize hour = _hour;
 18 @synthesize minute = _minute;
 19 @synthesize second = _second;
 20 @synthesize totalSeconds = _totalSeconds;
 21
 22 - (void)dealloc
 23 {
 24     [_lblShow release];
 25     [_strHour release];
 26     [_strMinute release];
 27     [_strSecond release];
 28     [super dealloc];
 29 }
 30
 31 - (id)initWithFrame:(CGRect)frame
 32 {
 33     self = [super initWithFrame:frame];
 34     if (self) {
 35         _lblShow = [[UILabel alloc] initWithFrame:self.bounds];
 36         _lblShow.backgroundColor = [UIColor clearColor];
 37         _lblShow.font = [UIFont systemFontOfSize:15];
 38         _lblShow.textColor = [UIColor yellowColor];
 39         _lblShow.textAlignment = NSTextAlignmentCenter;
 40         _lblShow.numberOfLines = 1;
 41         [self addSubview:_lblShow];
 42     }
 43     return self;
 44 }
 45
 46 - (id)initWithFrame:(CGRect)frame andMinutesNum:(NSInteger)minute
 47 {
 48     if (self = [self initWithFrame:frame]) {
 49         self.totalSeconds = minute * 60;
 50         //多线程启动定时器
 51        [NSThread detachNewThreadSelector:@selector(startTimer) toTarget:self withObject:nil];
 52     }
 53     return self;
 54 }
 55 - (void)startTimer
 56 {
 57     _timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerFire) userInfo:nil repeats:YES];
 58     [[NSRunLoop currentRunLoop] run];
 59 }
 60 - (void)handleWithTotalSeconds
 61 {
 62     self.hour = _totalSeconds/3600;
 63     self.minute = _totalSeconds%3600/60;
 64     self.second = _totalSeconds%3600%60;
 65     if (_hour <= 0) {
 66         _lblShow.text = [NSString stringWithFormat:@"%@:%@",_strMinute,_strSecond];
 67     }else{
 68         _lblShow.text = [NSString stringWithFormat:@"%@:%@:%@",_strHour,_strMinute,_strSecond];
 69     }
 70 }
 71 - (void)setHour:(NSInteger)hour
 72 {
 73     _hour = hour;
 74     if (_hour < 10) {
 75         self.strHour = [NSString stringWithFormat:@"0%d",_hour];
 76     }else{
 77         self.strHour = [NSString stringWithFormat:@"%d",_hour];
 78     }
 79 }
 80 - (void)setMinute:(NSInteger)minute
 81 {
 82     _minute = minute;
 83     if (_minute < 10) {
 84         self.strMinute = [NSString stringWithFormat:@"0%d",_minute];
 85     }else{
 86         self.strMinute = [NSString stringWithFormat:@"%d",_minute];
 87     }
 88 }
 89 - (void)setSecond:(NSInteger)second
 90 {
 91     _second = second;
 92     if (_second < 10) {
 93         self.strSecond = [NSString stringWithFormat:@"0%d",_second];
 94     }else{
 95         self.strSecond = [NSString stringWithFormat:@"%d",_second];
 96     }
 97 }
 98 - (void)setTotalSeconds:(NSInteger)totalSeconds
 99 {
100     _totalSeconds = totalSeconds;
101     [self performSelectorOnMainThread:@selector(handleWithTotalSeconds) withObject:nil waitUntilDone:YES];
102 }
103 - (void)timerFire
104 {
105     if (_totalSeconds == 0) {
106         [_timer invalidate];
107         return;
108     }
109     self.totalSeconds -= 1;
110 }
111 @end

解决iOS程序UI主线程和定时器相互阻塞的问题

时间: 2024-10-29 19:06:28

解决iOS程序UI主线程和定时器相互阻塞的问题的相关文章

Android子线程更新UI主线程方法之Handler

背景: 我们开发应用程序的时候,处于线程安全的原因子线程通常是不能直接更新主线程(UI线程)中的UI元素的,那么在Android开发中有几种方法解决这个问题,其中方法之一就是利用Handler处理的. 下面说下有关Handler相关的知识. 多线程一些基础知识回顾:在介绍Handler类相关知识之前,我们先看看在Java中是如何创建多线程的方法有两种:通过继承Thread类,重写Run方法来实现通过继承接口Runnable实现多线程 具体两者的区别与实现,看看这篇文章中的介绍:http://de

Android:子线程向UI主线程发送消息

在Android里,UI线程是不允许被阻塞的,因此我们要将耗时的工作放到子线程中去处理. 那么子线程耗时处理后要怎样通知UI线程呢? 我们可以在UI主线程中创建一个handler对象,然后通过重写其handleMessage(Message msg)的方法,该方法会接收到子线程中的handler对象的sendMessage((Message msg)发回来的消息.这样一发一收就完成工作: 而关于主线程向子线程发送消息的内容可以看我的上一篇博客,其中讲到了Looper类及其两个重要方法和实现原理.

【Android开发经验】来来来,同学,咱们讨论一下“只能在UI主线程更新View”这件小事

转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 "只能在UI主线程中更新View". 这句话很熟悉吧? 来来,哥们,看一下下面的例子 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) f

Android,UI主线程与子线程

在一个Android 程序开始运行的时候,会单独启动一个Process.默认的情况下,所有这个程序中的Activity或者Service(Service和 Activity只是Android提供的Components中的两种,除此之外还有Content Provider和Broadcast Receiver)都会跑在这个Process. 一个Android 程序默认情况下也只有一个Process,但一个Process下却可以有许多个Thread.          在这么多Thread当中,有一

ios 中请求主线程刷新UI

1 if ([NSThread isMainThread]) 2 { 3 [self.downloadMapBtn setImage:[UIImage imageNamed:@"download_map.png"] forState:UIControlStateNormal]; 4 [self.downloadMapBtn setNeedsDisplay]; 5 } 6 else 7 { 8 dispatch_sync(dispatch_get_main_queue(), ^{ 9 /

Android应用程序UI硬件加速渲染技术简要介绍和学习计划

Android系统的流畅性一直被拿来与iOS比较,并且认为不如后者.这一方面与Android设备硬件质量参差不齐有关,另一方面也与Android系统的实现有关.例如在3.0前,Android应用程序UI绘制不支持硬件加速.不过从4.0开始,Android系统一直以"run fast, smooth, and responsively"为目标对UI进行优化.本文对这些优化进行简要介绍和制定学习计划. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!

Handler详解4-epoll、looper.loop主线程阻塞

句柄与指针的区别 学习C++的人都知道句柄和指针,而且我发现很多人在句柄与指针之间直接划等号,对我们来说两者都是地址,我觉的这也造成很多人将句柄和指针划等号的直接原因. 首先说指针吧.通俗一点就是地址,他是内存的编号,通过它我们可以直接对内存进行操作,只要地址不变,我们每次操作的物理位置是绝对不变,记住这句话,这是句柄和指针的重大区别所在. 再说说句柄吧,一般是指向系统的资源的位置,可以说也是地址.但是这些资源的位置真的不变,我们都知道window支持虚拟内存的技术,同一时间内可能有些资源被换出

Android应用程序UI硬件加速渲染环境初始化过程分析

在Android应用程序中,我们是通过Canvas API来绘制UI元素的.在硬件加速渲染环境中,这些Canvas API调用最终会转化为Open GL API调用(转化过程对应用程序来说是透明的).由于Open GL API调用要求发生在Open GL环境中,因此在每当有新的Activity窗口启动时,系统都会为其初始化好Open GL环境.这篇文章就详细分析这个Open GL环境的初始化过程. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! Open

关于pthread_join函数在使用时如何不阻塞主线程的一种探索

pthread_join 函数是会阻塞主线程的,这会让很多java程序员不适应.因为在java中 start以后一个线程就执行执行了.主线程不会被阻塞. 而在linux中 join是会阻塞的. 那么如何使用join的时候 不阻塞主线程呢.我给出了一个解决方法. #include <stdio.h> #include <pthread.h> void *print_count(int c); void thread_start(); int main(int argc, char c