iOS Swift如何逐步绘制到UIImage?

问题描述 投票:1回答:1

如何使用iOS核心图形在单个图像中逐步绘制大型数据集?

我有一些代码可以立即处理整个数据集(超过100,000个矩形)并生成一个图像。这是一个非常长时间运行的操作,我希望这个数据集一次增量绘制1000个矩形,显示这些小图像更新(如90年代从互联网下载的图像)

我的问题是:在整个操作过程中我是否会保留对相同context的引用并简单地添加元素? - 或者 - 我是否应该使用UIGraphicsGetImageFromCurrentImageContext()捕获当前图像,然后在新的上下文中绘制它并在其上绘制其他矩形?

奖金问题 - 如果我想使用多个线程附加到同一图像,这是正确的方法吗?

   let context = UIGraphicsGetCurrentContext()!

    context.setStrokeColor(borderColor)
    context.setLineWidth(CGFloat(borderWidth))
    for elementIndex in 0 ..< data.count {

        context.setFillColor(color.cgColor)
        let marker = CGRect(x: toX(elementIndex),
                            y: toY(elementIndex),
                            width: rectWidth,
                            height: rectHeight)

        context.addRect(marker)
        context.drawPath(using: .fillStroke)
    }
    // Save the context as a new UIImage
    let myImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    if let cgImage = myImage?.cgImage,
        let orientation = myImage?.imageOrientation {

        return UIImage(cgImage: cgImage, scale: 2, orientation: orientation)
    }
uiimage swift4 drawing core-graphics ios12
1个回答
1
投票

你应该:

  • 将整个事件发送到一些后台队列;
  • 定期调用UIGraphicsGetImageFromCurrentImageContext并将图像视图更新分派给主队列

例如,这将每1/4秒更新图像视图:

DispatchQueue.global().async {
    var lastDrawn = CACurrentMediaTime()

    UIGraphicsBeginImageContextWithOptions(size, false, 0)

    for _ in 0 ..< 100_000 {
        // draw whatever you want

        let now = CACurrentMediaTime()
        if now - lastDrawn > 0.25 {
            self.updateImageView()
            lastDrawn = now
        }
    }

    self.updateImageView()

    UIGraphicsEndImageContext()
}

哪里:

func updateImageView() {
    guard let image = UIGraphicsGetImageFromCurrentImageContext() else { return }

    DispatchQueue.main.async {
        self.imageView.image = image
    }
}

从而:

func buildImage(of size: CGSize) {
    DispatchQueue.global().async {
        var lastDrawn = CACurrentMediaTime()

        UIGraphicsBeginImageContextWithOptions(size, false, 0)

        for _ in 0 ..< 100_000 {
            self.someColor().setFill()
            UIBezierPath(rect: self.someRectangle(in: size)).fill()

            let now = CACurrentMediaTime()
            if now - lastDrawn > 0.25 {
                self.updateImageView()
                lastDrawn = now
            }
        }

        self.updateImageView()

        UIGraphicsEndImageContext()
    }
}

func updateImageView() {
    let image = UIGraphicsGetImageFromCurrentImageContext()
    DispatchQueue.main.async {
        self.imageView.image = image
    }
}

func someRectangle(in size: CGSize) -> CGRect {
    let x = CGFloat.random(in: 0...size.width)
    let y = CGFloat.random(in: 0...size.height)
    let width = CGFloat.random(in: 0...(size.width - x))
    let height = CGFloat.random(in: 0...(size.height - y))

    return CGRect(x: x, y: y, width: width, height: height)
}

func someColor() -> UIColor {
    return UIColor(red: .random(in: 0...1),
                   green: .random(in: 0...1),
                   blue: .random(in: 0...1),
                   alpha: 1)
}

产量:

enter image description here

现在,我不是直接调用CoreGraphics,但你可以,它也可以正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.