Производительность с CoreGraphics - PullRequest
0 голосов
/ 25 апреля 2020

Я пытаюсь обновлять свой пользовательский вид каждые 1/30 секунды (30FPS). Вид показывает множество точек, идущих в случайных направлениях.

class DotsDistributionUIView: NSView {
    private var timer = Timer()

    var lastPoints: [[Point]] = [[]]
    ...

    init(frame frameRect: NSRect) {
        super.init(frame: frameRect)

        startTimer()
    }
    ...

    @objc func reloadLayout() {
        self.setNeedsDisplay(frame)
    }

    func startTimer() {
        lastPoints = [[]]
        timer.invalidate()
        timer = Timer.scheduledTimer(timeInterval: 1/30, target: self, selector: #selector(self.reloadLayout), userInfo: nil, repeats: true)
   }

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        let context = NSGraphicsContext.current!.cgContext
        for (i, x) in stride(from: 0, through: Double(frame.width), by: Double(frame.width/sqrt(CGFloat( config.numEntities.wrappedValue)))).enumerated() {
            for (j, y) in stride(from: 0, through: Double(frame.height), by: Double(frame.height/sqrt(CGFloat( config.numEntities.wrappedValue)))).enumerated() {
                var point: CGPoint
                if lastPoints.indices.contains(i) {
                    if lastPoints[i].indices.contains(j) {
                        if lastPoints[i][j].rect == frame {
                            var step: (Double, Double)
                            repeat {
                                if lastPoints[i][j].lastStep == (0,0) {
                                    step = (randomNumber(in: -0.5...0.5), randomNumber(in: -0.5...0.5))//(Double.random(in: -0.5...0.5), Double.random(in: -0.5...0.5))
                                } else {
                                    var changeX = randomNumber(in: -0.1...0.1)//Double.random(in: -0.1...0.1)
                                    var changeY = randomNumber(in: -0.1...0.1)//Double.random(in: -0.1...0.1)
                                    if abs(lastPoints[i][j].lastStep.0 + changeX) > 1 {
                                        var factor = (changeX/abs(changeX))
                                        factor.negate()
                                        changeX = 0.1 * factor
                                    }
                                    if abs(lastPoints[i][j].lastStep.1 + changeY) > 1 {
                                        var factor = (changeY/abs(changeY))
                                        factor.negate()
                                        changeY = 0.1 * factor
                                    }
                                    step = (lastPoints[i][j].lastStep.0 + changeX, lastPoints[i][j].lastStep.1 + changeY)
                                }

                                if !frame.contains(CGPoint(x: lastPoints[i][j].x + step.0, y: lastPoints[i][j].y + step.1)) {
                                    step.0.negate()
                                    step.1.negate()
                                }
                            } while !frame.contains(CGPoint(x: lastPoints[i][j].x + step.0, y: lastPoints[i][j].y + step.1))
                            lastPoints[i][j].lastStep = step
                            point = CGPoint(x: lastPoints[i][j].x + step.0, y: lastPoints[i][j].y + step.1)
                        } else {
                            point = CGPoint(x: x, y: y)
                        }
                        lastPoints[i][j].coordinates = point
                    } else {
                        point = CGPoint(x: x, y: y)
                        lastPoints[i].append(Point(on: frame, i, j, x, y, config: config))
                    }
                } else {
                    point = CGPoint(x: x, y: y)
                    lastPoints.append([Point(on: frame, i, j, x, y, config: config)])
                }
                context.move(to: point)
                context.addArc(center: point, radius: 2, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: false)
                context.setFillColor(NSColor.blue.cgColor)
                context.fillPath()
            }
        }
    }
}

Моя пользовательская структура Point просто хранит координаты и некоторую дополнительную информацию, ничего интересного. В двух циклах я задаю количество точек, которые рисую. Приблизительно в двухстах точках мой взгляд становится запаздывающим и не успевает за обновлением 1/30 секунды Из-за производительности я пытался использовать другой генератор случайных чисел (см .: Xoshiro). Но это только ячмень помог. Что я могу сделать, чтобы улучшить производительность?

...