UIView draw (_ rect: CGRect) не работает с многопоточностью - PullRequest
0 голосов
/ 27 ноября 2018
class GradientChart: LineChartView {

private let accessQueue = DispatchQueue(label: "SynchronizedColor", qos: .userInteractive)
private var color: UIColor?

override func draw(_ rect: CGRect) {
    accessQueue.async {
        self.updateColors()

        DispatchQueue.main.async {
            super.draw(rect)
        }
    }
}

func updateColors() {
    if self.color != nil
        self.dataSet.setColor(self.color!)
        self.dataSet.fillColor = self.color!
        self.color = nil
    }
}

func setColor(_ color: UIColor) {
    accessQueue.async() {
        self.color = color
    }
}  

LineChartView - это класс из библиотеки Charts

Я использую serial accessQueue для поточно-ориентированной работы с LineChartView и переменной цвета.Когда super.draw (rect) вызывается на DispatchQueue.main, я вижу пустой белый экран.

Я отладил функцию draw () LineChartView и обнаружил, что UIGraphicsGetCurrentContext () возвращает nil.Почему?

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Думайте о текущем графическом контексте для этого представления как о двери, которая автоматически открывается непосредственно перед тем, как drawRect начинает работать и закрывается, когда она заканчивается.

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

Итак, ваш код работает следующим образом:

// the door opens
override func draw(_ rect: CGRect) {
    accessQueue.async {
        // the door closes
        self.updateColors()
        DispatchQueue.main.async {
            super.draw(rect)
        }
    }
}

Как только дверь закрывается, текущий графический контекст отсутствует, и всем командам рисования некуда идти.Таким образом, весь ваш код бесполезен.

отладил drawC () LineChartView и обнаружил, что UIGraphicsGetCurrentContext () возвращает nil.Почему?

Вот почему.К тому времени, когда код запускается, больше нет графического контекста.

0 голосов
/ 27 ноября 2018

UIKit ожидает, что все рисование будет выполнено в главном потоке.Если вы хотите рисовать в фоновом режиме, вам нужно использовать графику Core на уровне CALayer.См. Документацию для CALayer.drawsAsynchronously

...