Код, который запускается под управлением среды выполнения общего языка (CLR), известен как управляемый код. Код, который не запускается в среде CLR, известен как собственный код.
То, что вы сделали, это непосредственно для рисования одной линии. Вы используете первое касание в своих методах touch
, а также у вас есть только одна «текущая строка».
Я бы пошел с чем-то вроде следующего. Я надеюсь, что код говорит сам за себя:
class Line {
var start: CGPoint = .zero
var end: CGPoint = .zero
}
private var finishedLines: [Line] = [Line]()
private var currentLines: [UITouch: Line] = [UITouch: Line]()
private func insertNewPoint(_ point: CGPoint, forTouch touch: UITouch) {
if let line = currentLines[touch] {
line.end = point
} else {
currentLines[touch] = {
let newLine = Line()
newLine.start = point
return newLine
}()
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
touches.forEach { touch in
insertNewPoint(touch.location(in: self.view), forTouch: touch)
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
touches.forEach { touch in
insertNewPoint(touch.location(in: self.view), forTouch: touch)
}
}
private func finishLine(at point: CGPoint, forTouch touch: UITouch) {
guard let line = currentLines[touch] else { return }
currentLines[touch] = nil
line.end = point
self.finishedLines.append(line)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
touches.forEach { touch in
finishLine(at: touch.location(in: self.view), forTouch: touch)
}
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesCancelled(touches, with: event)
touches.forEach { touch in
finishLine(at: touch.location(in: self.view), forTouch: touch)
}
}
Так что, где вы обрабатываете прикосновения, наиболее важно перебрать все из них touches.forEach { touch in
. И вам нужен набор строк, которые в вашем случае должны быть назначены на штрихи. Он должен работать с использованием словаря [UITouch: Line]
.
Полный пример:
import UIKit
class ViewController: UIViewController {
private var finishedLines: [Line] = [Line]()
private var currentLines: [UITouch: Line] = [UITouch: Line]()
private var lineView: LineView?
override func viewDidLoad() {
super.viewDidLoad()
self.view.isMultipleTouchEnabled = true
self.lineView = {
let view = LineView(frame: self.view.bounds)
view.isUserInteractionEnabled = false
self.view.addSubview(view)
return view
}()
}
private func updateDrawing() {
lineView?.lines = finishedLines + currentLines.map { [111].value }
lineView?.setNeedsDisplay()
}
private func insertNewPoint(_ point: CGPoint, forTouch touch: UITouch) {
if let line = currentLines[touch] {
line.end = point
} else {
currentLines[touch] = {
let newLine = Line()
newLine.start = point
return newLine
}()
}
updateDrawing()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
touches.forEach { touch in
insertNewPoint(touch.location(in: self.view), forTouch: touch)
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
touches.forEach { touch in
insertNewPoint(touch.location(in: self.view), forTouch: touch)
}
}
private func finishLine(at point: CGPoint, forTouch touch: UITouch) {
guard let line = currentLines[touch] else { return }
currentLines[touch] = nil
line.end = point
self.finishedLines.append(line)
updateDrawing()
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
touches.forEach { touch in
finishLine(at: touch.location(in: self.view), forTouch: touch)
}
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesCancelled(touches, with: event)
touches.forEach { touch in
finishLine(at: touch.location(in: self.view), forTouch: touch)
}
}
}
// MARK: - Line
extension ViewController {
class Line {
var start: CGPoint?
var end: CGPoint?
}
}
// MARK: - LineView
extension ViewController {
class LineView: UIView {
var lines: [Line]?
override func draw(_ rect: CGRect) {
super.draw(rect)
// Fill white background
UIColor.white.setFill()
UIBezierPath(rect: rect).fill()
// Draw all lines
UIColor.red.setStroke()
lines?.forEach { line in
if let start = line.start, let end = line.end {
let path = UIBezierPath()
path.move(to: start)
path.addLine(to: end)
path.stroke()
}
}
}
}
}
Вы можете вставить этот код во вновь созданный проект Xcode iOS в свой ViewController
, и он должен работать.
Каждый из touchesBegan...
, touchesMoved...
, touchesEnded...
, touchesCancelled...
имеет набор касаний в качестве входного параметра. Система гарантирует, что у каждого пальца одинаковые UITouch
от начала до конца / отменены.
Прямо сейчас вы обрабатываете только один палец, используя touches.first
. Вместо этого вам нужно нарисовать отдельную линию для каждого прикосновения. Что-то вроде:
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
touches.forEach { touch in
line[touch]?.end = touch.location(in: self)
}
setNeedsDisplay()
}