CATiledLayer drawLayer:inContext всегда вызывается в основном потоке - MacOS El Capitan

Я использую NSView с поддержкой CATiledLayer (Mac, а не iOS) и согласно документам Apple https://developer.apple.com/reference/quartzcore/catiledlayer Я ожидаю, что это будет вызываться асинхронно, в нескольких потоках для повышения производительности, однако кажется, что это когда-либо вызывается только в основном потоке.

Я делаю работу в drawLayer(layer: CALayer, inContext ctx: CGContext)

Я включил canDrawConcurrently в NSView, а также удостоверился, что для окна установлено значение allowsConcurrentViewDrawing как true (по умолчанию), но оно по-прежнему всегда вызывает основной поток для каждого прямоугольника плитки.

Мне нужно выполнить некоторые манипуляции с изображением перед отображением в зависимости от области прямоугольника, требующей отображения, и работа в основном потоке влияет на производительность.

Любые идеи, как я могу заставить его вызывать фоновый поток?

Я попытался упорядочить изображение в фоновом потоке, а затем вызвать основную очередь со следующим, но он отображает пустой прямоугольник:

backgroundQueue.addOperationWithBlock({ [ weak self ] in            
    guard let strongSelf = self else { return }

    // ** This is the part I nee to do in background that can take some time
    guard let image = strongSelf.imageForTileRect(layerBounds, imageSize: imageSize) else { return }
    // ** End background bit

    var rect = layerBounds
    let rectImageRef = image.CGImageForProposedRect(&rect, context: nil, hints: nil)

    if (rectImageRef != nil) {
        NSOperationQueue.mainQueue().addOperationWithBlock({ 
            CGContextDrawImage(ctx, rect, rectImageRef)
        })
    }
})

person Herwr    schedule 19.09.2016    source источник
comment
Вы когда-нибудь догадывались об этом? Я вижу то же самое. Я хочу использовать фоновый поток для рисования моего CATiledLayer для моего NSView.   -  person Stephen Johnson    schedule 31.01.2017
comment
Еще немного контекста здесь. Если я добавлю еще один CATiledLayer в качестве наложения на тот, который является моим фоновым наложением, он будет отображаться в фоновом режиме. Только основной, который является поддержкой для моего представления в основном потоке. Я могу в конечном итоге сделать основной пустой и поместить свой рендеринг в оверлей CATiledLayer.   -  person Stephen Johnson    schedule 01.02.2017


Ответы (2)


На самом деле нам никогда не удавалось заставить его работать, когда CATiledLayer был основным слоем, я не уверен, почему он не работает, и мы так и не получили ответа от возникшей ошибки Apple.

Однако мы заставили его работать, выполняя фоновый рендеринг, сделав основной слой стандартным CALayer, а затем добавив CATiledLayer в качестве подслоя к этому основному, аналогично коду ниже.

Мы также заметили, что он работал должным образом при размещении CATiledLayer в NSView.

Надеюсь это поможет...

class HostingLayer : CALayer {

    var tiledLayer : CATiledLayer!

    override init() {
        super.init()

        self.tiledLayer = CATiledLayer.init()

        self.addSublayer(tiledLayer!)
    }
}
person Herwr    schedule 08.02.2017

Итак, вот что я сделал, это работает, хотя и не идеально. В drawRect: для моего CATiledLayer подложки NSView я рисую простой фон (в моем случае простую сетку). Я создал еще один CATiledLayer и добавил в него слой моего NSView в качестве подслоя и установил NSView в качестве его делегата. Этот второй `CATiledLayer' получает вызовы отрисовки делегата в фоновом потоке.

person Stephen Johnson    schedule 02.02.2017