Здравствуйте. Я пытаюсь нарисовать несколько прямоугольников на UIImage, если пользователь начинает касаться изображения и перетаскивает его в желаемое конечное положение прямоугольника, но мое решение довольно медленное, и я не знаю почему.
Итак, это моя функция рисования:
func drawRectangleOnImage(image: UIImage, pos1: CGPoint, pos2: CGPoint) -> UIImage {
let imageSize = image.size
let scale: CGFloat = 0
UIGraphicsBeginImageContextWithOptions(imageSize, false, scale)
image.draw(at: CGPoint.zero)
let scaling = image.size.height/mainImageView.frame.height
let rectangle = CGRect(x: pos1.x*scaling, y: pos1.y*scaling, width: abs(pos2.x-pos1.x)*scaling, height: abs(pos2.y-pos1.y)*scaling)
UIColor.black.setFill()
UIRectFill(rectangle)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
, и она называется так:
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let position = touch.location(in: mainImageView)
self.endPosition = position
}
guard let img = mainImageView.image else {
return
}
mainImageView.image = drawRectangleOnImage(image: img, pos1: self.startPosition, pos2: self.endPosition)
}
Поэтому, когда я касаюсь дисплея и рисую прямоугольник, двигая пальцем, нужно около 2 секунд, чтобы прямоугольник появился внутри симулятора. Является ли способ рисования прямоугольника устаревшим или что не так с этим кодом?
Обновление с помощью решения Matts для создания собственного UIView для этого:
import UIKit
import Foundation
class DetectionView : UIView {
lazy var rectangles: [CGRect] = []
lazy var tempPointStart = CGPoint(x: 0, y: 0)
lazy var tempPointEnd = CGPoint(x: 0, y: 0)
override init(frame: CGRect) {
super.init(frame:frame)
backgroundColor = .gray
let g = UIPanGestureRecognizer(target: self, action: #selector(pan))
self.addGestureRecognizer(g)
}
@objc
func pan(_ g:UIGestureRecognizer) {
print(g.location(in: self).x)
switch g.state {
case .began:
print(g.location(in: self))
tempPointStart = g.location(in: self)
case .changed:
tempPointEnd = g.location(in: self)
self.setNeedsDisplay()
case .ended:
tempPointEnd = g.location(in: self)
rectangles.append(CGRect(x: self.tempPointStart.x, y: self.tempPointStart.y, width: self.tempPointEnd.x-self.tempPointStart.x, height: self.tempPointEnd.y-self.tempPointStart.y))
self.tempPointStart = CGPoint(x:0,y:0)
self.tempPointEnd = CGPoint(x:0,y:0)
self.setNeedsDisplay()
default: break
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func draw(_ rect: CGRect) {
let con = UIGraphicsGetCurrentContext()!
//user is still drawing
if(self.tempPointStart.x != self.tempPointEnd.x || self.tempPointStart.y != self.tempPointEnd.y) {
for rect in rectangles {
con.addRect(rect)
}
con.addRect(CGRect(x: self.tempPointStart.x, y: self.tempPointStart.y, width: self.tempPointEnd.x-self.tempPointStart.x, height: self.tempPointEnd.y-self.tempPointStart.y))
}
else {
for rect in rectangles {
con.addRect(rect)
}
}
con.strokePath()
}
}
Итак в UIView это работает довольно хорошо, но теперь моя проблема в том, что я не знаю, как добавить изображение к этому представлению элегантным способом. Я пытался реализовать его как UIImageView, но затем функциональность рисования прямоугольников была потеряна. Я мог бы загрузить его как фоновое изображение для этого представления, но я не уверен, насколько хорошо это будет работать, потому что изображения могут быть в любом формате, поэтому я должен быть осторожен с форматами изображений.
У вас есть идея загрузить изображение в это представление элегантным способом?