【问题标题】:CGContext donesn't work correctly in threadCGContext 在线程中无法正常工作
【发布时间】:2012-09-19 10:52:33
【问题描述】:

我正在尝试使用 Core Graphics 从另一个线程在自定义 UIView 中进行无限绘图。获取当前的CGContext 是不可能的,所以我尝试创建一个新的。但我不知道如何将它应用到视图中。

这是我在自定义视图中使用的代码:

CG_INLINE CGContextRef CGContextCreate(CGSize size)
{
    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
    CGContextRef ctx = CGBitmapContextCreate(nil, size.width, size.height, 8, size.width * (CGColorSpaceGetNumberOfComponents(space) + 1), space, kCGImageAlphaPremultipliedLast);
    CGColorSpaceRelease(space);

    return ctx;
}
- (void)drawRect:(CGRect)rect 
{
    CGContextRef context = CGContextCreate(self.bounds.size);
    if(context)
    {
        [self.layer renderInContext:context];
        [self drawSymbolsInContext:context];
        CGContextRelease(context);
    }
}
- (void)drawSymbolsInContext:(CGContextRef)context
{
    for (int x = 0; x<[cellsArray count];x++)
    {
        for(int y=0; y<[[cellsArray objectAtIndex:x] count]; y++)
        {
            NSLog(@"lol %d", y);

            float white[] = {1.0, 1.0, 1.0, 1.0};
            CGContextSetFillColor(context, white);
            CGContextFillRect(context, [self bounds]);

            CGContextSetTextDrawingMode(context, kCGTextStroke);
            CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0);
            CGContextSelectFont(context, "Times", 12.0, kCGEncodingMacRoman);
                                CGAffineTransform xform = CGAffineTransformMake(
                                                                                1.0,  0.0,
                                                                                0.0, -1.0,
                                                                                0.0,  0.0);
            CGContextSetTextMatrix(context, xform);
            CGContextShowTextAtPoint(context, 100.0, 100.0 + 15*y, "test", strlen("test"));
        }
    }
}

这是我用来运行thead的代码(在ViewController中):

- (void)viewDidLoad
{
    [super viewDidLoad];
    [NSThread detachNewThreadSelector:@selector(SomeAction:) toTarget:self withObject:self.view];
}

- (void) SomeAction:(id)anObject
{
    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
    DrawView *drawView = (DrawView *)anObject;

    while (1)
    {
        COLOR col;
        col.blue = 100;
        col.red = 100;
        col.green = 200;

        int cellX = 0;
        int cellY = [[rowsArray objectAtIndex:0] count];

        CELL cel;
        cel.x = cellX;
        cel.x = cellY;

        SymbolAlive *s = [[SymbolAlive alloc] initWithColor:col andFrame:cel];

        [[rowsArray objectAtIndex:0] addObject:s];
        [drawView drawRect:drawView.bounds];

        [NSThread sleepForTimeInterval: 0.1];
    }
    [NSThread exit];
    [autoreleasepool release];
}

循环正确运行。但是屏幕上什么也没有显示。

有什么想法吗?

【问题讨论】:

  • 为什么要在drawRect 中创建一个新上下文,而不是使用当前提供的上下文,即CGContext context = UIGraphicsGetCurrentContext();
  • 不可能从另一个线程获取当前上下文。将出现无效的上下文错误。 UIGraphicsGetCurrentContext() 给出空结果。

标签: ios thread-safety core-graphics drawrect cgcontext


【解决方案1】:

我猜你必须在主线程上进行绘图。而不是

    [drawView drawRect:drawView.bounds];

这样做

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

然后创建一个类似的绘图函数

    - (void)doDraw:(id)notused
    {
        [drawView drawRect:drawView.bounds];
    }

这将允许您在后台进行处理,但在主线程上进行绘图。

此外,在这种情况下,您应该使用标准图形上下文。

还有一条评论,您可能还可以将所有绘图移入上下文线程,然后在主线程上调用 renderInContext。

【讨论】:

  • 标准上下文仍然返回为空
  • 如果您改为调用 [self setNeedsDisplay] 会发生什么?在这种情况下,当前上下文绝对不应该是零
  • 应该是[drawView setNeedsDisplay](将调用drawRect)
  • 尝试调用 setNeedsDisplay 而不是 drawRect。未调用 drawRect 方法。太诡异了……
  • 如果您从主线程(直接或通过 performSelectorOnMainThread)调用 [drawView setNeedsDisplay],则肯定应该在您的自定义视图中调用 drawRect。
猜你喜欢
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多