在背景线程上绘制上下文



我有一个UIView,它必须显示一些信息。由于这个视图非常复杂,而且绘图需要大量的时间,所以我将它移到了背景线程中,以避免阻塞主线程。绘制完成后,我将调度回主线程以设置ImageView。

下面的代码为我绘制了图形,但我偶尔会遇到一些崩溃。通常xcode指向[view release];并表示Thread 6: Program received signal: EXC_BAD_ACCESS

NSManagedObjectID *objectID = [self.managedObject objectID];
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
        dispatch_async(queue,^{
            NSManagedObjectContext *backgroundContext = [[NSManagedObjectContext alloc] init];
            [backgroundContext setPersistentStoreCoordinator:[[self.managedObject managedObjectContext] persistentStoreCoordinator]];
            NSManagedObject *mo = [backgroundContext objectWithID:objectID];
            CGImageRef resultImage;
            CGContextRef context;
            void *bitmapData;
    CGRect frame = self.frame;
    frame.origin = CGPointZero;
    CGColorSpaceRef colorSpace;
    CGSize canvasSize;
    int bitmapByteCount;
    int bitmapBytesPerRow;
    canvasSize = frame.size;
    CGFloat scale = [UIScreen instancesRespondToSelector:@selector(scale)] ? [[UIScreen mainScreen] scale] : 1.0f;
    canvasSize.width *= scale;
    canvasSize.height *= scale;
    bitmapBytesPerRow = (canvasSize.width * 4);
    bitmapByteCount = (bitmapBytesPerRow * canvasSize.height);
    //Create the color space
    colorSpace = CGColorSpaceCreateDeviceRGB();
    bitmapData = malloc( bitmapByteCount );
    //Check the the buffer is alloc'd
    if( bitmapData == NULL ){
        DLog(@"Buffer could not be alloc'd");
    }
    //Create the context
    context = CGBitmapContextCreate(bitmapData, canvasSize.width, canvasSize.height, 8, bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
    CGContextClearRect(context, CGRectMake(0, 0, canvasSize.width, canvasSize.height));
    // Setup transformation
    CGContextSetInterpolationQuality(context, kCGInterpolationNone);
    CGContextTranslateCTM(context, 0.0f, canvasSize.height); 
    CGContextScaleCTM(context, scale, -scale);
    UIView *view = [[UIView alloc] initWithFrame:frame];
    [view setBackgroundColor:[UIColor clearColor]];
    UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(137, 5, 255, 30)];
    [nameLabel setFont:[UIFont fontWithName:@"Arial" size:22.0f]];
    [nameLabel setText:[mo valueForKey:@"name"]];
    [nameLabel setTextAlignment:UITextAlignmentRight];
    [view addSubview:nameLabel];
    [nameLabel release];
    nameLabel = nil;
    ... Creating 20 or so label/imageviews all use 'mo' for data access to the NSManagedObject.
    [view.layer renderInContext:context];
    [view release];
    view = nil;
    //Get the result image
    resultImage = CGBitmapContextCreateImage(context);
    UIImage *viewImage = [UIImage imageWithCGImage:resultImage scale:0.0 orientation:UIImageOrientationUp];
    dispatch_async(dispatch_get_main_queue(),^ {
        [dataImageView setImage:viewImage];
    });
    //Cleanup
    free(bitmapData);
    CGColorSpaceRelease(colorSpace);
    CGImageRelease(resultImage);  
    CGContextRelease(context);
}); 

希望你们能帮助我,因为我对此一无所知。我曾尝试使用NSZombieEnabled YES运行它,这有时会在控制台-[UILabel hash]: message sent to deallocated instance 0x22841c00 中导致以下错误

尝试调查此问题的可能来源:当您创建UILabel时,您将它们添加到UIView中,然后释放它们(这没关系),但您也将它们"清零"。因此,在这一点上,您有UILabel,它由UIView保留,但同时它指向nil!因此,在发布"视图"的最后,它将尝试释放其子视图,一旦遇到保留计数为1但为零的UILabel,就会出现"已释放实例"异常。这可以说明调试器为什么在[view release]停止,以及NSZombieEnabled为什么会抱怨试图解除分配UILabel:当指针指向nil时,它会将其视为已解除分配。因此,可能的解决方案是:删除"nameLabel=nil"语句。

最新更新