Objective C Cocoa 从单独的线程更新 gui
我有一个线程正在增加变量“int count”的值。我想用“int count”的新值更新我的用户界面,直到我通过按停止按钮停止增量。我已设法更新用户界面,但内存占用量不断增加。它并不显示为内存泄漏,而是一个分配问题。每次从线程调用 UI 元素时,堆大小都会增加。我可以清楚地看到仪器泄漏分配部分,我有一些分配,只有在移动触摸 UI 元素的窗口时才会被释放。尽管尝试了一切,我还是没能解决这个问题。 如果有更好的方法用“int count”新值更新 UI 元素,请随时告诉我。 谢谢,
如果您想使用仪器或分配运行来查看问题或查看源代码,我在下面发布了可可项目的链接。这是一个小项目,只有几行代码。
-(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
}
I have a thread which is incrementing the value of the variable "int count" . I want to update my UI with the new value of "int count" until I stop the increment by pressing the stop button. I've manage to update the UI but the memory footprint keep on growing. It doesn't show as a memory leak but it is an allocation problem.the heap size is being increased every time there is a call to a UI element from the thread. I can clearly see instruments leaks allocation part that I have some allocations which are only being freed when moving the Window of touching a UI element. I did not manage to solve the problem despite trying everything.
If there is a better way to update UI elements with "int count" new value, feel free to let me know.
Thanks
I posted the link to the cocoa project below if you want to run with instrument or allocation to see the problem or look at the source. It' a small project just a few lines.
-(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
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
1) 首先,您不应该从主线程以外的线程更新 UI!
_向 mainThread 发布通知,要求其更新 UI,或使用
performSelector:onMainThread:
或 GCD 和get_main_queue()
,或任何使主线程更新的解决方案用户界面。[编辑] 抱歉,我错过了您调用
performSelectorOnMainThread:
的代码部分,所以没关系。2)此外,使用线程来满足您的需要确实没有必要。一般来说,您应该避免线程,而更喜欢其他技术,例如 NSOperationQueues、GCD,甚至 RunLoop 调度。
在您的情况下,使用线程 usleep(5000) 只是开销,并且会产生许多与多线程相关的问题(请阅读 Apple 的并发编程指南和线程编程指南)。
你可以使用重复的
NSTimer
来做同样的事情,它会更容易编码和管理,并且会避免你很多麻烦。1) First of all, you should never update the UI from a thread other than the main thread !
_Post a notification to the mainThread to ask it to update the UI, or use
performSelector:onMainThread:
or GCD andget_main_queue()
, or whatever solution to make the main thread update the UI.[EDIT] Sorry I missed the part of your code where you call
performSelectorOnMainThread:
so that's OK.2) Moreover, using a thread for what you need is really not necessary. In general you should avoid thread, an prefer other techniques like NSOperationQueues, GCD, or even RunLoop scheduling.
In your case, using a thread an usleep(5000) is just overhead and will arise a lot of problems related to multithreading (read Apple's Concurrency Programming Guide and Threading Programming Guide).
You could do the same thing using a repeating
NSTimer
, it will be much more easier to code and manage, and will avoid you a lot of trouble.嗯..让我们尝试释放由
performSelectorOnMainThread
调用创建的后台对象(如果有)。Hmm.. let's try to release behind-the-scene objects created by
performSelectorOnMainThread
calls, if any.