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

iphone线程初学者问题,管理自动释放池有问题,iphone,multithreading,Iphone,Multithreading,我在一个简单的线程示例中遇到了问题。我知道我的方法还没有完成,但是现在,我想按下开始按钮,让它触发一个线程,该线程每秒递增一个计数器。我知道它正确地连接在IB中,因为NSLog告诉我它可以访问我的TimerRead方法。但随后它立即跳回最初的myThread,而没有到达updateDisplay方法并释放池,这就是为什么我猜我的程序实际上没有增加计数器的原因。我原以为我会把它放在睡眠时间或其他什么的,但最终我认为我错过了实现这一目标的正确方法。任何想法都很好。谢谢 @implementation

我在一个简单的线程示例中遇到了问题。我知道我的方法还没有完成,但是现在,我想按下开始按钮,让它触发一个线程,该线程每秒递增一个计数器。我知道它正确地连接在IB中,因为NSLog告诉我它可以访问我的TimerRead方法。但随后它立即跳回最初的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

简单的回答是您没有安排计时器

iOS(和其他)使用运行循环。每个线程可能有一个运行循环,主UI线程为您设置了一个运行循环。简单地说,一个运行循环保持一个要做事情的队列,要么按顺序进行,要么阻塞,直到有事情要做

使用活动UI所做的任何事情,如设置UILabel的文本,都必须在主线程上完成。在您的情况下,您已在主线程上设置(但未计划)计时器以更新计时器。安排计时器只是意味着将其添加到运行循环中

如果要执行的任务很长,最终会更新UI,则可以使用performSelectorInBackground启动长任务,并在任务完成时使用performSelectorOnMainThread更新UI

如果您有一个短期的周期性任务,例如更新时钟或计数器UI,那么您可以在希望启动计时器的同一线程上创建一个NSTimer。创建计时器时,请使用scheduledTimerWithTimeInterval变量,使其自动启动

创建重复计时器时,必须保留对其的引用,以便在释放目标之前使计时器无效。最晚,在dealloc中,您应该使计时器无效

将timerThread转换为startTimer,而不是调用startThread

-(void) startTimer {
    timerMember = [[NSTimer
      scheduledTimerWithTimeInterval:1.0
                              target:self
                            selector:@selector(updateDisplay:)
                            userInfo:nil
                             repeats:YES] retain];
}

-(void) dealloc {
     [timerMember invalidate];
     [timerMember release];
     ...
}

在我看来,你想做的事不需要任何线索。您所需要的只是NSTimer(您已经完成了);它们是一种先进的技术,如果你做得不对,它会给你带来各种各样的问题。至于计时器,DrawForward的回答非常好。