从后台任务调用-setNeedsDisplay请求麻烦?

时间:2009-08-17 20:27:34

标签: iphone cocoa-touch

我有一个更新视图的后台任务。该任务调用-setNeedsDisplay来绘制视图。

这有效:

- (void) drawChangesTask;
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    if (pixels) {
        drawChanges((UInt32 *) origPixels, (UInt32 *) pixels, CGBitmapContextGetBytesPerRow(ctx)/4, CGBitmapContextGetHeight(ctx), count--);

        if (count < 0) {
            count = 150;
        }
        else
            [self performSelectorInBackground:@selector(drawChangesTask) withObject:nil ];

        [self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO ];

    }
    [pool release];
}

这不起作用:

- (void) drawChangesTask;
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    if (pixels) {
        drawChanges((UInt32 *) origPixels, (UInt32 *) pixels, CGBitmapContextGetBytesPerRow(ctx)/4, CGBitmapContextGetHeight(ctx), count--);

        if (count < 0) {
            count = 150;
        }
        else
            [self performSelectorInBackground:@selector(drawChangesTask) withObject:nil ];

        [self setNeedsDisplay];

    }
    [pool release];
}

任何人都知道为什么?当我说它不起作用时,我的意思是它会运行数十次迭代,有时我会看到我的图像部分向上或向下移动,或者完全空白,然后欺骗者在某处给我一个“EXC_BAD_ACCESS” CoreGraphics中。

另外,如果我自己没有处理自动释放池,那么我会收到泄漏的错误消息。不明白为什么会这样。我的drawChanges()不会创建任何新对象。这是错误:

2009-08-17 11:41:42.358 BlurApp[23974:1b30f] *** _NSAutoreleaseNoPool(): Object 0xd78270 of class NSThread autoreleased with no pool in place - just leaking

2 个答案:

答案 0 :(得分:8)

UIKit根本不是线程安全的 - 你需要调用在主线程上更新UIKit控件的方法。

我认为这一行:

[self performSelectorInBackground:@selector(drawChangesTask) withObject:nil];

造成麻烦。您是否尝试过在当前线程上再次调用它?如果您需要在调用之间执行runloop,请使用:

[self performSelector:@selector(drawChangesTask) withObject:nil afterDelay:0.0];

这将在您进入的方法完成后,在当前线程上调用该方法,并且runloop已经过了一次。

答案 1 :(得分:2)

这里的问题是UIKit不是线程安全的,如果你告诉你的UI从后台线程做一些事情,那么你可以保证,你想要做的是使用performSelectorOnMainThread方法对你的UI元素进行更新