Как обновить/перерисовать/перезагрузить UIGraphicsImageRenderer в iOS с помощью Swift

63
7

У меня есть пользовательский класс UIView который рисует некоторые строки с помощью UIGraphicsImageRenderer, и у меня есть некоторые слайдеры для изменения точек, используемых для рисования линий, но при этом не стираются старые строки, а просто рисуются поверх них сверху. Я попытался добавить self.setNeedsDisplay() рядом с верхней и нижней частью метода, и не self.setNeedsDisplay() никакого значения.

Я получил основную идею о том, как использовать UIGraphicsImageRenderer из проекта hackingwithswift 27 - в этом проекте он использует оператор switch для вызова разных функций для рисования разных вещей, и это, кажется, ясно и хорошо перерисовывает.

Я также попробовал var clearsContextBeforeDrawing: Bool = true, но я не думаю, что использую его правильно, я нашел его в документации.

Я также видел в документации setNeedsDisplay: "Вы должны использовать этот метод, чтобы запросить, чтобы представление было перерисовано только при изменении содержимого или внешнего вида представления. Если вы просто изменяете геометрию представления, представление обычно не перерисовывается" "Я предполагаю, что" геометрия зрения "означает такие вещи, как трансформации (масштабирование/перевод/вращение)?

func drawLines(pointList: [CGPoint],
cycle: Bool = false,
lineColor: CGColor = UIColor.blue.cgColor,
fillColor: CGColor = UIColor.clear.cgColor) {

// self.setNeedsDisplay()
let renderer = UIGraphicsImageRenderer(size: CGSize(width: 728, height: 984))
// var clearsContextBeforeDrawing: Bool = true
let img = renderer.image { ctx in
ctx.cgContext.move(to: pointList[0])

for v in pointList.dropFirst() {
ctx.cgContext.addLine(to: v)
}

ctx.cgContext.setStrokeColor(lineColor)
ctx.cgContext.strokePath()
}

let iv = UIImageView(image:img)
iv.frame.origin = CGPoint(x: 0, y: 0)
self.addSubview(iv)
// self.setNeedsDisplay()
}

спросил(а) 2021-01-25T18:43:56+03:00 4 месяца, 3 недели назад
1
Решение
63

Вы добавляете новый UIImageView каждый раз, когда вы вызываете drawLines(). То, как написан ваш код, каждое изображение имеет четкий фон... поэтому вы видите свои "линии", расположенные друг над другом.

Вы должны иметь один UIImageView уже добавляемый к self (мы будем называть его theDrawingImageView), а затем измените функцию, чтобы закончить с:

    //let iv = UIImageView(image:img)
//iv.frame.origin = CGPoint(x: 0, y: 0)
//self.addSubview(iv)

theDrawingImageView.image = img
}

Редактировать: Вот полная демонстрация. Вы можете запустить это прямо на странице игровой площадки.

Он создает контроллер вида и добавляет UIButton и UIImageView. Каждый раз, когда вы нажимаете кнопку, будет создан набор из 12 случайных точек и используется для рисования линий на новом UIImage который затем используется для установки свойства .image изображения.

import UIKit
import PlaygroundSupport

class TestViewController : UIViewController {

let theDrawingImageView: UIImageView = {
let v = UIImageView()
v.backgroundColor = UIColor.lightGray
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()

let btn: UIButton = {
let b = UIButton()
b.setTitle("Tap to Draw Lines", for: .normal)
b.backgroundColor = .red
b.translatesAutoresizingMaskIntoConstraints = false
return b
}()

override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = UIColor(red: 0.25, green: 0.5, blue: 1.0, alpha: 1.0)

// add button and image view to self.view
self.view.addSubview(btn)
self.view.addSubview(theDrawingImageView)

// button position
btn.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
btn.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 20.0).isActive = true

// image view position
theDrawingImageView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
theDrawingImageView.topAnchor.constraint(equalTo: btn.bottomAnchor, constant: 20.0).isActive = true

// image view width and height
theDrawingImageView.widthAnchor.constraint(equalToConstant: 300.0).isActive = true
theDrawingImageView.heightAnchor.constraint(equalToConstant: 300.0).isActive = true

// add a target for the button tap
btn.addTarget(self, action: #selector(btnTapped(_:)), for: .touchUpInside)

}

// simple random number function
func random(_ range:Range<Int>) -> Int {
return range.lowerBound + Int(arc4random_uniform(UInt32(range.upperBound - range.lowerBound)))
}

func btnTapped(_ sender: Any) {

var pts = [CGPoint]()

let maxX = Int(theDrawingImageView.bounds.size.width)
let maxY = Int(theDrawingImageView.bounds.size.height)

// generate a set of 12 random points
for _ in 1...12 {
let x = random(0..<maxX)
let y = random(0..<maxY)
let pt = CGPoint(x: x, y: y)
pts.append(pt)
}

drawLines(imageView: theDrawingImageView, pointList: pts)

}

func drawLines(imageView: UIImageView,
pointList: [CGPoint],
cycle: Bool = false,
lineColor: CGColor = UIColor.blue.cgColor,
fillColor: CGColor = UIColor.clear.cgColor) {

let renderer = UIGraphicsImageRenderer(size: imageView.bounds.size)

// this creates a new UIImage and draws lines on it
let img = renderer.image { ctx in

ctx.cgContext.move(to: pointList[0])

for v in pointList.dropFirst() {
ctx.cgContext.addLine(to: v)
}

ctx.cgContext.setStrokeColor(lineColor)
ctx.cgContext.strokePath()

}

// set the image view .image to the new image with the lines drawn on it
imageView.image = img
}

}

let vc = TestViewController()
PlaygroundPage.current.liveView = vc

ответил(а) 2021-01-25T18:43:56+03:00 4 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема