objective c cocoa从一个单独的线程更新gui

时间:2011-09-30 12:08:20

标签: objective-c cocoa objective-c++

我有一个增加变量“int count”值的线程。我想用新的“int count”值更新我的UI,直到我按下停止按钮停止增量。我已经设法更新UI,但内存占用不断增长。它没有显示为内存泄漏,但它是一个分配问题。每次从线程调用UI元素时,堆大小都会增加。我可以清楚地看到仪器泄漏分配部分,我有一些分配,只有在移动触摸UI元素的窗口时才被释放。尽管尝试了一切,我仍无法解决问题。 如果有更好的方法来更新具有“int count”新值的UI元素,请随时告诉我。 感谢

如果您想使用仪器或分配运行以查看问题或查看源代码,我将链接发布到下面的cocoa项目。这是一个只有几行的小项目。

Xcode Poject GUI UPDATE LINK

-(void) incrementCountGUI:(id)param{ // increment count and update gui
  NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];// pool just added

    count++;
    if (count>=100) {// MAKE SURE COUNT DOESN'T GO ABOVE 100
        count=0;
    }
    [sliderDisplayOutlet setIntValue:count];// display value of count in textfield
    [sliderOutlet setIntValue:count];// move slider to value of count

    [pool release];
}


+(void) updateSliderThread:(id)param{// this thread will call incrementCountGUI method to continuously upgrade UI in the background

    NSAutoreleasePool *myThreadPool=[[NSAutoreleasePool alloc]init];
while (shoudStop==NO) {
    [ sharedAppInstance performSelectorOnMainThread:@selector(incrementCountGUI:) // update ui in main thread
                                         withObject:nil
                                      waitUntilDone:NO];
    usleep(5000);// sleep microsec; 
}   
    [myThreadPool release]; 
}

- (IBAction)stopCountAction:(id)sender {// START OR STOP counter thread

    if ([stopCountButtonOutlet state]==1) { // button depressed=>START
        shoudStop=NO;
        [NSThread detachNewThreadSelector:@selector(updateSliderThread:) toTarget:[AppController class] withObject:nil];
        [stopCountButtonOutlet setTitle: @" STOP" ];

    }
    if ([stopCountButtonOutlet state]==0){//button depressed=> STOP thread

        shoudStop=YES;

        [stopCountButtonOutlet setTitle:@" START INCREMENTING COUNT FROM THREAD "];

    }


}

- (IBAction)sliderAction:(id)sender { // you can change the value of the variable count manualy.
 count=[sliderOutlet intValue];
[sliderDisplayOutlet setIntValue:count];// display value of count


}

2 个答案:

答案 0 :(得分:1)

1)首先,您应该从不从主线程以外的线程更新UI!

_向mainThread发送通知,要求其更新用户界面,或者使用performSelector:onMainThread:或GCD和get_main_queue(),或者使主线程更新用户界面的任何解决方案。

[编辑]抱歉,我错过了您致电performSelectorOnMainThread:的代码部分,这样就可以了。


2)此外,使用线程满足您的需求是非常必要的。一般来说,你应该避免使用线程,更喜欢其他技术,如NSOperationQueues,GCD,甚至是RunLoop调度。

在你的情况下,使用一个线程usleep(5000)只是开销,并且会出现许多与多线程相关的问题(阅读Apple的并发编程指南和线程编程指南)。

您可以使用重复的NSTimer 执行相同的操作,编码和管理会更容易,并且会避免您遇到很多麻烦。

答案 1 :(得分:-1)

嗯..让我们尝试发布performSelectorOnMainThread次呼叫创建的幕后对象(如果有的话)。

+(void) updateSliderThread:(id)param
{
    NSAutoreleasePool *myThreadPool=[[NSAutoreleasePool alloc]init];
    int drainCount = 0;   
    while (shoudStop==NO)
    {
        [ sharedAppInstance performSelectorOnMainThread:@selector(incrementCountGUI:)
                                             withObject:nil
                                          waitUntilDone:NO];
        usleep(5000);// sleep microsec; 

        // Release pooled objects about every 5 seconds
        if (++drainCount >= 1000)
        {
            [myThreadPool release];
            myThreadPool = [[NSAutoreleasePool alloc]init];
            drainCount = 0;
        }
    }   
    [myThreadPool release]; 
}