0

I'm trying to make infinite drawing in custom UIView from another thread using Core Graphics. It's impossible to obtain current CGContext so I try to create a new one. But I have no idea how to apply it to the view.

Here is the code I use in my custom view:

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"));
        }
    }
}

Here is code I use to run thead(in 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];
}

Loop runs correctly. But nothing is displayed on the screen.

Any ideas?

Rafael Kayumov
  • 226
  • 1
  • 11
  • Why are you creating a new context in `drawRect` as opposed to using the currently provided context, i.e. `CGContext context = UIGraphicsGetCurrentContext();`? – FluffulousChimp Sep 19 '12 at 11:18
  • It's impossible to get current context from another thread. Invalid context error will appear. UIGraphicsGetCurrentContext() gives null result. – Rafael Kayumov Sep 19 '12 at 11:24

1 Answers1

1

I'm guessing you have to do your drawing on the main thread. Instead of

    [drawView drawRect:drawView.bounds];

Do this

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

and then create a draw function like

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

That will allow you to do the processing in the background but do the drawing on the main thread.

Also, you should be using the standard graphics context in this case.

One more comment, you can probably also move all your drawing-into-the-context into the background thread, but then call renderInContext on the main thread.

Mike M
  • 4,358
  • 1
  • 28
  • 48