iphone线程初学者问题,管理自动释放池有问题

时间:2010-07-22 03:59:15

标签: iphone multithreading

我遇到一个简单的线程示例问题。我知道我的方法并不完整,但是到目前为止,我想按下开始按钮,然后关闭一个每秒增加一个计数器的线程。我知道它正确地连接在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

1 个答案:

答案 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];
     ...
}