我遇到一个简单的线程示例问题。我知道我的方法并不完整,但是到目前为止,我想按下开始按钮,然后关闭一个每秒增加一个计数器的线程。我知道它正确地连接在IB中,因为NSLog告诉我它到达了我的timerThread方法。但是它立即跳回到初始myThread,没有达到updateDisplay方法并释放池,这就是为什么我猜我的程序实际上没有增加一个计数器。我以为我会把它放在一个睡眠间隔或什么的,但最后我想我错过了实现这一目标的正确方法。任何想法都会很棒。谢谢!
@implementation MainController
-(id)initWithLabel:(UILabel *)label {
if (self = [super init]) {
countLabel = label;
[countLabel retain];
}
return self;
}
-(int)count {
return count;
}
-(void)setCount:(int) value {
count = value;
}
-(void)updateDisplay:(NSTimer *)timer {
NSLog(@"%s", __FUNCTION__);
countLabel.text = [NSString stringWithFormat:@"%i", count];
count++;
}
-(void)timerThread {
NSLog(@"%s", __FUNCTION__);
[NSTimer timerWithTimeInterval:1.0
target:self
selector:@selector(updateDisplay:)
userInfo:nil
repeats:YES];
//NSNumber *threadID = [NSNumber numberWithInt:(int)threadID];
// threadLabel = [NSString stringWithFormat:@"%@", threadID];
}
-(void)myThread {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//NSNumber *threadID = [NSNumber numberWithInt:(int)threadID];
[self performSelectorOnMainThread:@selector(timerThread)
withObject:nil
waitUntilDone:NO];
// NSLog(@"threadID in myThread: %@", threadID);
[pool release];
}
-(void)startThread {
// threadIndex = 0;
// numThreads = 0;
// NSNumber *threadID = [NSNumber numberWithInt:threadIndex++];
[self performSelectorInBackground:@selector(myThread) withObject:nil];
// NSLog(@"%i", threadIndex);
numThreads++;
}
-(void)myThreadStop {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSThread exit];
[self performSelectorOnMainThread:@selector(updateDisplay)
withObject:nil
waitUntilDone:NO];
[pool release];
}
-(void)stopThread {
[self performSelectorInBackground:@selector(myThreadStop) withObject:nil];
}
-(void) dealloc {
[countLabel release];
[super dealloc];
}
@end
答案 0 :(得分:2)
简短的回答是你没有安排计时器。
iOS(和其他人)使用run loop。每个线程可能都有一个运行循环,主UI线程有一个为您设置的运行循环。简单地说,一个运行循环保持一个要做的事情的队列,或者以有序的方式或块进行,直到有事情要做。
您使用活动UI执行的任何操作(如设置UILabel的文本)都必须在主线程上完成。在您的情况下,您已在主线程上设置(但未安排)计时器以更新计时器。调度计时器只是意味着将它添加到运行循环中。
如果你有一个漫长的任务要执行,最后会更新UI,你可以使用performSelectorInBackground来启动冗长的任务,并在任务完成更新UI时执行SelectorOnMainThread。
如果您有一个简短的周期性任务,例如更新时钟或计数器UI,您可以在希望定时器触发的同一线程上创建NSTimer。创建计时器时,请使用scheduledTimerWithTimeInterval变体,以便它自动开始激活。
创建重复计时器时,必须保留对它的引用,以便在释放目标之前使计时器无效。最迟,在dealloc中你应该使计时器无效。
不要调用startThread,而是将timerThread转换为startTimer。
-(void) startTimer {
timerMember = [[NSTimer
scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(updateDisplay:)
userInfo:nil
repeats:YES] retain];
}
-(void) dealloc {
[timerMember invalidate];
[timerMember release];
...
}