2

我有自定义 UICollectionViewCell 子类,我在其中使用剪切、描边和透明度进行绘制。它在 Simulator 和 iPhone 5 上运行良好,但在旧设备上存在明显的性能问题。

所以我想把耗时的绘图移到后台线程。由于始终在主线程上调用 -drawRect 方法,因此我最终将绘制的上下文保存到 CGImage (原始问题包含使用 CGLayer 的代码,但正如 Matt Long 指出的那样,它有点过时了)。

这是我在此类中的 drawRect 方法的实现:

-(void)drawRect:(CGRect)rect {

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    if (self.renderedSymbol != nil) {
        CGContextDrawImage(ctx, self.bounds, self.renderedSymbol);
    }
}

定义此 renderSymbol 属性的渲染方法:

- (void) renderCurrentSymbol {

    [self.queue addOperationWithBlock:^{

// creating custom context to draw there (contexts are not thread safe)
        CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
        CGContextRef ctx = CGBitmapContextCreate(nil, self.bounds.size.width, self.bounds.size.height, 8, self.bounds.size.width * (CGColorSpaceGetNumberOfComponents(space) + 1), space, kCGImageAlphaPremultipliedLast);
        CGColorSpaceRelease(space);

// custom drawing goes here using 'ctx' context

// then saving context as CGImageRef to property that will be used in drawRect
        self.renderedSymbol = CGBitmapContextCreateImage(ctx);

// asking main thread to update UI    
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [self setNeedsDisplayInRect:self.bounds];
        }];

        CGContextRelease(ctx);

    }];
}

此设置在主线程上完美运行,但是当我用 NSOperationQueue 或 GCD 包装它时,我得到了很多不同的“无效上下文 0x0 ”错误。应用程序本身不会崩溃,但不会发生绘图。我想发布自定义创建的 CGContextRef 存在问题,但我不知道该怎么做。

这是我的财产声明。(我尝试使用原子版本,但这没有帮助)

@property (nonatomic) CGImageRef renderedSymbol;
@property (nonatomic, strong) NSOperationQueue *queue;
@property (nonatomic, strong) NSString *symbol; // used in custom drawing

属性的自定义设置器/获取器:

-(NSOperationQueue *)queue {
    if (!_queue) {
        _queue = [[NSOperationQueue alloc] init];
        _queue.name = @"Background Rendering";
    }
    return _queue;
}   
-(void)setSymbol:(NSString *)symbol {
    _symbol = symbol;
    self.renderedSymbol = nil;
    [self setNeedsDisplayInRect:self.bounds];
}

-(CGImageRef) renderedSymbol {
    if (_renderedSymbol == nil) {
        [self renderCurrentSymbol];
    }
    return _renderedSymbol;
}

我能做些什么?

4

2 回答 2

1

您是否注意到您引用的 CGLayer 上的文档自 2006 年以来一直没有更新?您认为 CGLayer 是正确解决方案的假设是不正确的。Apple 几乎放弃了这项技术,您可能也应该这样做:http: //iosptl.com/posts/cglayer-no-longer-recommended/使用核心动画。

于 2013-05-14T14:31:19.147 回答
1

通过 Mind Snacks 使用令人惊叹的第三方库 - MSCachedAsyncViewDrawing解决了问题。

于 2013-05-20T06:40:43.277 回答