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

Mind Snacks — MSCachedAsyncViewDrawingによるすばらしいサードパーティ ライブラリを使用して解決された問題。

于 2013-05-20T06:40:43.277 に答える
1

参照している CGLayer のドキュメントが 2006 年以降更新されていないことに気付きましたか? CGLayer が正しいソリューションであるというあなたの仮定は正しくありません。Apple はこの技術をほとんど放棄しており、おそらくあなたもそうすべきでしょう: http://iosptl.com/posts/cglayer-no-longer-recommended/ Core Animation を使用してください。

于 2013-05-14T14:31:19.147 に答える