Swift 3: How do I pinch to scale and rotate UIImageView? - swift

I am really struggling to find tutorials online as well as already answered questions (I have tried them and they don't seem to work). I have a UIImageView that I have in the centre of my view. I am currently able to tap and drag this wherever I want on screen. I want to be able to pinch to scale and rotate this view. How do I achieve this? I have tried the code for rotation below but it doesn't seem to work? Any help will be a massive help and marked as answer. Thank you guys.
import UIKit
class DraggableImage: UIImageView {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.backgroundColor = .blue
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
self.backgroundColor = .green
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let position = touch.location(in: superview)
center = CGPoint(x: position.x, y: position.y)
}
}
}
class CVController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(rotateAction(sender:)))
firstImageView.addGestureRecognizer(rotateGesture)
setupViews()
}
func rotateAction(sender: UIRotationGestureRecognizer) {
let rotatePoint = sender.location(in: view)
let firstImageView = view.hitTest(rotatePoint, with: nil)
firstImageView?.transform = (firstImageView?.transform.rotated(by: sender.rotation))!
sender.rotation = 0
}
let firstImageView: DraggableImage = {
let iv = DraggableImage()
iv.backgroundColor = .red
iv.isUserInteractionEnabled = true
return iv
}()
func setupViews() {
view.addSubview(firstImageView)
let firstImageWidth: CGFloat = 50
let firstImageHeight: CGFloat = 50
firstImageView.frame = CGRect(x: (view.frame.width / 2) - firstImageWidth / 2, y: (view.frame.height / 2) - firstImageWidth / 2, width: firstImageWidth, height: firstImageHeight)
}
}

You have a some problems in your code. First you need to add the UIGestureRecognizerDelegate to your view controller and make it your gesture recognizer delegate. You need also to implement shouldRecognizeSimultaneously method and return true. Second when applying the scale you need to save the transform when the pinch begins and apply the scale in top of it:
class DraggableImageView: UIImageView {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
backgroundColor = .blue
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
backgroundColor = .green
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let position = touches.first?.location(in: superview){
center = position
}
}
}
class ViewController: UIViewController, UIGestureRecognizerDelegate {
var identity = CGAffineTransform.identity
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setupViews()
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(scale))
let rotationGesture = UIRotationGestureRecognizer(target: self, action: #selector(rotate))
pinchGesture.delegate = self
rotationGesture.delegate = self
view.addGestureRecognizer(pinchGesture)
view.addGestureRecognizer(rotationGesture)
}
let firstImageView: DraggableImageView = {
let iv = DraggableImageView()
iv.backgroundColor = .red
iv.isUserInteractionEnabled = true
return iv
}()
func setupViews() {
view.addSubview(firstImageView)
let firstImageWidth: CGFloat = 50
let firstImageHeight: CGFloat = 50
firstImageView.frame = CGRect(x: view.frame.midX - firstImageWidth / 2, y: view.frame.midY - firstImageWidth / 2, width: firstImageWidth, height: firstImageHeight)
}
#objc func scale(_ gesture: UIPinchGestureRecognizer) {
switch gesture.state {
case .began:
identity = firstImageView.transform
case .changed,.ended:
firstImageView.transform = identity.scaledBy(x: gesture.scale, y: gesture.scale)
case .cancelled:
break
default:
break
}
}
#objc func rotate(_ gesture: UIRotationGestureRecognizer) {
firstImageView.transform = firstImageView.transform.rotated(by: gesture.rotation)
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}

Related

How can I end a touch/gesture with a long hold?

I'd like to move a simple, small UIView around the screen and 'drop' it off at any location on the screen, but accurately. Simply lifting your finger from the screen does not have the desired effect as there is always some movement upon lifting your finger, resulting in the object not being in the required location.
What I'm looking for is some way to count down a specified number of milliseconds AFTER holding/pausing at the desired location and then have some mechanism ENDING my touches/gesture so the object is placed EXACTLY where I want it.
I've been reasonably successful with touchesBegan/Moved/Ended, but even though I called the touchesEnded method the touches never really end as I can still drag around the object on the screen and relocate it - not what I want.
import UIKit
class ViewController: UIViewController {
let greenDot : UIView = {
let greenDot = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
greenDot.backgroundColor = .green
greenDot.layer.cornerRadius = greenDot.bounds.height / 2
return greenDot
}()
var timer : Timer?
var lastTouch = Set<UITouch>()
var lastTouchEvent: UIEvent?
override func viewDidLoad() {
super.viewDidLoad()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
print(touch.location(in: view))
greenDot.center = touch.location(in: view)
view.addSubview(greenDot)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
print(touch.location(in: view))
if timer != nil { timer?.invalidate() }
greenDot.center = touch.location(in: view)
view.addSubview(greenDot)
lastTouch = touches
lastTouchEvent = event
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(stopTouches), userInfo: nil, repeats: false)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
timer?.invalidate()
print("Touches Ended #: \(touch.location(in: view))")
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
print("Cancelling touch")
}
#objc func stopTouches() {
touchesEnded(lastTouch, with: lastTouchEvent)
// touchesCancelled(lastTouch, with: lastTouchEvent)
// view.resignFirstResponder()
}
}
With UIGestures I have tried with the UILongPressGestureRecognizer, but I don't know how to 'end' with a long-press. Do I use 2 long-presses in sequence - one to start the movement and another to end the movement? I like the longPress since it is continuous and I can thus pan with it.
import UIKit
class ViewController: UIViewController {
let greenDot : UIView = {
let dot = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
dot.backgroundColor = .green
dot.layer.cornerRadius = dot.frame.width/2
return dot
}()
override func viewDidLoad() {
super.viewDidLoad()
let longPress1 = UILongPressGestureRecognizer(target: self, action: #selector(press1))
longPress1.minimumPressDuration = 0.2
view.addGestureRecognizer(longPress1)
}
#objc func press1(_ sender: UILongPressGestureRecognizer) {
let newLocation = sender.location(in: view)
greenDot.backgroundColor = .green
greenDot.frame = CGRect(x: 0, y: 0, width: 10, height: 10)
greenDot.center = CGPoint(x: newLocation.x, y: newLocation.y - 40)
if sender.state == .ended {
greenDot.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
greenDot.center = CGPoint(x: newLocation.x, y: newLocation.y - 40)
greenDot.backgroundColor = .purple
}
view.addSubview(greenDot)
}
}
So in conclusion: I'm looking for a method to place an object, which I am moving around on the screen with my finger, accurately.
Any help in this regard will be greatly appreciated.
Intriguing how often you end up answering your own question after placing it before others.
So after many days of fumbling around I stumbled across this pointer from Apple:
https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/implementing_a_custom_gesture_recognizer/implementing_a_discrete_gesture_recognizer
In short, I have the basics of what I was looking for by creating a custom Gesture Recognizer. Thanks Apple.
So for anyone else who might be interested, following is the 'basic' code for grabbing an object, moving it around and letting a timer release it for you so that the drop is as accurate as needed. Releasing before the timer expires also works, but then some shifting might/will occur during release. Once the timer has fired and your finger is still on the screen, you will be unable to accidentally drag the object out of place.
Obviously there is still a lot of work needed before implementing in an app to mitigate errors. 'Small steps'
import UIKit
import UIKit.UIGestureRecognizerSubclass
class ObjectDropGestureRecognizer: UIGestureRecognizer {
var trackedTouch : UITouch? = nil
var intervalTime : Double = 1.0
var dropTimer : Timer?
var counter : Int = 0
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
print(touches.count)
if touches.count != 1 {
self.state = .failed
}
if self.state == .possible {
self.state = .began
print("began...")
}
if self.trackedTouch == nil {
self.trackedTouch = touches.first
} else {
for touch in touches {
if touch != self.trackedTouch {
self.ignore(touch, for: event)
}
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)
guard let newTouch = touches.first else { return }
self.state = .changed
counter += 1
print("Changed...\(counter)")
if self.dropTimer != nil { dropTimer?.invalidate() }
dropTimer = Timer.scheduledTimer(withTimeInterval: intervalTime, repeats: false) { timer in
print("Timer fired")
print(newTouch.location(in: self.view))
self.state = .ended
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesEnded(touches, with: event)
if self.dropTimer != nil {
self.dropTimer?.invalidate()
self.state = .ended
}
self.state = .recognized
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesCancelled(touches, with: event)
self.trackedTouch = nil
self.state = .cancelled
}
override func reset() {
super.reset()
self.trackedTouch = nil
self.counter = 0
}
}
class ViewController: UIViewController {
let greenDot : UIView = {
let dot = UIView(frame: CGRect(x: 50, y: 200, width: 20, height: 20))
dot.backgroundColor = .green
dot.layer.cornerRadius = dot.frame.width/2
return dot
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(greenDot)
let objectMoveGesture = ObjectDropGestureRecognizer(target: self, action: #selector(tapAction(_:)))
objectMoveGesture.intervalTime = 0.8
view.addGestureRecognizer(objectMoveGesture)
}
#objc func tapAction(_ touch: ObjectDropGestureRecognizer){
let newLocation = touch.location(in: view)
greenDot.center = CGPoint(x: newLocation.x, y: newLocation.y)
}
}

remove all drawing in imageview UIGraphicsGetImageFromCurrentImageContext

I want to remove everything written imageview pic. I have tried something like pic.Clear() but its not being recognized. I dont know what else to do. The only other thing I can think off is to somehow create a variable that is like a line because I cant access the lines right now outside of the func they are in now. I am trying to do this is in clearM. Using UIGraphicsGetImageFromCurrentImageContext has something to do with this. I dont want to use pencil kit.
import UIKit
class ViewController: UIViewController {
var startPoint: CGPoint?
var statPoint = CGPoint.zero
var swipe = false
var pic = UIImageView()
var clearBtn = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
[pic,clearBtn].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
}
pic.backgroundColor = .brown
clearBtn.backgroundColor = .blue
pic.frame = CGRect(x: 100, y: 100, width: 250, height: 250)
clearBtn.frame = CGRect(x: 100, y: 350, width: 50, height: 50)
clearBtn.addTarget(self, action: #selector(clearM), for: .touchDown)
}
#objc func clearM(){
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return}
swipe = false
statPoint = touch.location(in: self.pic)
}
var score = 0
func drawLine(from fromPoint: CGPoint, to toPoint : CGPoint) {
UIGraphicsBeginImageContext( pic.frame.size)
guard let context = UIGraphicsGetCurrentContext() else {
return
}
pic.image?.draw(in: pic.bounds)
context.move(to: fromPoint)
context.addLine(to: toPoint)
context.setLineCap(.round)
context.setLineWidth(5)
context.setStrokeColor(UIColor.black.cgColor)
context.strokePath()
pic.image = UIGraphicsGetImageFromCurrentImageContext()
pic.alpha = 1
UIGraphicsEndImageContext()
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return
}
swipe = true
let currentPoint = touch.location(in: pic)
drawLine(from: statPoint, to: currentPoint)
statPoint = currentPoint
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if !swipe {
drawLine(from: statPoint, to: statPoint)
}
UIGraphicsBeginImageContext(pic.frame.size)
pic.image?.draw(in: pic.bounds, blendMode: .normal, alpha: 1)
pic.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
}

line drawing away from touch point

My swift code is attempting to draw a line. As you can see in the gif below. When the the user places a touch point you can the line being drawn a little away from the cursor. I don't know what's going on here. But I would assume whatever that is wrong is in the touches began func because this issue starts as soon as the user touches the image view.
import UIKit
class ViewController: UIViewController {
var startPoint: CGPoint?
var statPoint = CGPoint.zero
var swipe = false
var pic = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
pic.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(pic)
pic.backgroundColor = .brown
view.backgroundColor = .cyan
pic.frame = CGRect(x: 100, y: 100, width: 250, height: 250)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return}
swipe = false
statPoint = touch.location(in: view)
}
func drawLine(from fromPoint: CGPoint, to toPoint : CGPoint) {
UIGraphicsBeginImageContext( view.frame.size)
guard let context = UIGraphicsGetCurrentContext() else {
return
}
pic.image?.draw(in: view.bounds)
context.move(to: fromPoint)
context.addLine(to: toPoint)
context.setLineCap(.round)
context.setLineWidth(5)
context.setBlendMode(.normal)
context.setStrokeColor(UIColor.black.cgColor)
context.strokePath()
pic.image = UIGraphicsGetImageFromCurrentImageContext()
pic.alpha = 1
UIGraphicsEndImageContext()
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard var touch = touches.first else {
return
}
swipe = true
let currentPoint = touch.location(in: view)
drawLine(from: statPoint, to: currentPoint)
statPoint = currentPoint
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if !swipe {
drawLine(from: statPoint, to: statPoint)
}
UIGraphicsBeginImageContext(view.frame.size)
pic.image?.draw(in: view.bounds, blendMode: .normal, alpha: 1)
pic.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
}
///
the problem with your image view fame :
please set like this and check :
class ViewController: UIViewController {
var startPoint: CGPoint?
var statPoint = CGPoint.zero
var swipe = false
var pic = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
pic.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(pic)
pic.backgroundColor = .brown
view.backgroundColor = .cyan
pic.frame = CGRect(x: 100, y: 100, width: 250, height: 250)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else {
return}
swipe = false
statPoint = touch.location(in: self.pic)
}
func drawLine(from fromPoint: CGPoint, to toPoint : CGPoint) {
UIGraphicsBeginImageContext( pic.frame.size)
guard let context = UIGraphicsGetCurrentContext() else {
return
}
pic.image?.draw(in: pic.bounds)
context.move(to: fromPoint)
context.addLine(to: toPoint)
context.setLineCap(.round)
context.setLineWidth(5)
context.setBlendMode(.normal)
context.setStrokeColor(UIColor.black.cgColor)
context.strokePath()
pic.image = UIGraphicsGetImageFromCurrentImageContext()
pic.alpha = 1
UIGraphicsEndImageContext()
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard var touch = touches.first else {
return
}
swipe = true
let currentPoint = touch.location(in: pic)
drawLine(from: statPoint, to: currentPoint)
statPoint = currentPoint
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if !swipe {
drawLine(from: statPoint, to: statPoint)
}
UIGraphicsBeginImageContext(pic.frame.size)
pic.image?.draw(in: pic.bounds, blendMode: .normal, alpha: 1)
pic.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
}
please check the code i updated your controller

draw line only in one direction starting with cgpoint

My swifts codes goal below is to be able to draw a straight line. When the uiview is touch the user can only draw 90 degrees above the initial point. The direction has already ben decided. So the user can just draw the line above the point that is touched. You can the gif below the line on the left is what my code does below. The line on the right is what I would like to acheive.
import UIKit
class ViewController: UIViewController{
var draw = Canvas()
override func viewDidLoad() {
super.viewDidLoad()
[draw].forEach {
view.addSubview($0)
$0.translatesAutoresizingMaskIntoConstraints = false}
}
override func viewDidLayoutSubviews() {
draw.backgroundColor = .clear
NSLayoutConstraint.activate ([
draw.bottomAnchor.constraint(equalTo: view.bottomAnchor),
draw.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.77, constant: 0),
draw.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1, constant: 0),
draw.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant : 0),
])
}
}
struct ColoredLine {
var color = UIColor.black
var points = [CGPoint]()
var width = 5
}
class Canvas: UIView {
var strokeColor = UIColor.red
var strokeWidth = 5
func undo() {
_ = lines.popLast()
setNeedsDisplay()
}
func clear() {
lines.removeAll()
setNeedsDisplay()
}
var lines = [ColoredLine]()
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
lines.forEach { (line) in
for (i, p) in line.points.enumerated() {
if i == 0 {
context.move(to: p)
} else {
context.addLine(to: p)
}
}
context.setStrokeColor(line.color.cgColor)
context.setLineWidth(CGFloat(line.width))
context.strokePath()
context.beginPath()
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
var coloredLine = ColoredLine()
coloredLine.color = strokeColor
coloredLine.width = strokeWidth
lines.append(coloredLine)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let point = touches.first?.location(in: self) else { return }
guard var lastLine = lines.popLast() else { return }
lastLine.points.append(point)
lines.append(lastLine)
setNeedsDisplay()
}
}
It is OK to manufacture the coordinates, Points consists of x and y.
Keeping the y, and done.
keep the first point for one touch event
var firstPt: CGPoint?
// get the first point
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let first = touches.first?.location(in: self) else { return }
// store first as property
firstPt = first
}
manufacture the rest points, the x of new get points is irrelevant
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let point = touches.first?.location(in: self), let first = firstPt else { return }
let pointNeeded = CGPoint(x: first.x , y: point.y)
// ... , do as usual
}
and in touchesEnd and touchesCancell, firstPt = nil

my code doesn't draw a line, it only draws a very tiny circle

My code isn't behaving the way I want it, why is the so? I don't understand what went wrong. So I'm playing around with swift, trying to transition from android to swift, I'm trying to make this simple app that draws lines, its not working as I want it, can someone please help me with what I'm doing wrong?
//
// DrawView.swift
// IOSTouch
import Foundation
import UIKit
class DrawView: UIView {
var currentLine: Line?
var finishedLines = [Line]();
//for debug
let line1 = Line(begin: CGPoint(x:50,y:50), end: CGPoint(x:100,y:100));
let line2 = Line(begin: CGPoint(x:50,y:100), end: CGPoint(x:100,y:300));
func strokeLine(line: Line){
//Use BezierPath to draw lines
let path = UIBezierPath();
path.lineWidth = 5;
path.lineCapStyle = CGLineCap.round;
path.move(to: line.begin);
path.addLine(to: line.end);
path.stroke(); //actually draw the path
}
override func draw(_ rect: CGRect) {
//draw the finished lines
UIColor.black.setStroke() //finished lines in black
for line in finishedLines{
strokeLine(line: line);
}
//for debug
strokeLine(line: line1);
strokeLine(line: line2);
//draw current line if it exists
if let line = currentLine {
UIColor.red.setStroke(); //current line in red
strokeLine(line: line);
}
}
//Override Touch Functions
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print(#function) //for debugging
let touch = touches.first!; //get first touch event and unwrap optional
let location = touch.location(in: self); //get location in view co-ordinate
currentLine = Line(begin: location, end: location);
setNeedsDisplay(); //this view needs to be updated
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
//TODO
setNeedsDisplay()
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
//TODO
setNeedsDisplay()
}
override func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
//TODO
}
#IBInspectable var finishedLineColor: UIColor = UIColor.black {
didSet {
setNeedsDisplay()
}
}
#IBInspectable var currentLineColor: UIColor = UIColor.red {
didSet {
setNeedsDisplay()
}
}
#IBInspectable var lineThickness: CGFloat = 10 {
didSet {
setNeedsDisplay()
}
}
}
another file
import Foundation
import CoreGraphics
struct Line {
var begin = CGPoint.zero
var end = CGPoint.zero
}
This code is works, I use it:
import UIKit
class ViewController: UIViewController {
var firstPoint: CGPoint?
var secondPoint: CGPoint?
var currentLine: CAShapeLayer?
override func viewDidLoad() {
super.viewDidLoad()
}
func addLine(fromPoint start: CGPoint, toPoint end:CGPoint) {
let line = CAShapeLayer()
let linePath = UIBezierPath()
linePath.move(to: start)
linePath.addLine(to: end)
line.path = linePath.cgPath
line.strokeColor = UIColor.black.cgColor
line.lineWidth = 3
line.lineJoin = kCALineJoinRound
self.view.layer.addSublayer(line)
}
func setCurrentLine(fromPoint start: CGPoint, toPoint end: CGPoint) {
let line = CAShapeLayer()
let linePath = UIBezierPath()
linePath.move(to: start)
linePath.addLine(to: end)
line.path = linePath.cgPath
line.strokeColor = UIColor.red.cgColor
line.lineWidth = 3
line.lineJoin = kCALineJoinRound
currentLine = line
if let current = currentLine {
self.view.layer.addSublayer(current)
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
firstPoint = touches.first?.location(in: self.view)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
currentLine?.removeFromSuperlayer()
currentLine = nil
if let first = firstPoint, let current = touches.first?.location(in: self.view) {
setCurrentLine(fromPoint: first, toPoint: current)
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
secondPoint = touches.first?.location(in: self.view)
if let first = firstPoint, let second = secondPoint {
addLine(fromPoint: first, toPoint: second)
currentLine?.removeFromSuperlayer()
currentLine = nil
}
}
}
It should work now
override func touchesMoved(_ touches: Set, with event: UIEvent?) {
print(#function)
let touch = touches.first!
let location = touch.location(in: self);
currentLine?.end = location;
setNeedsDisplay();
}
override func touchesEnded(_ touches: Set, with event: UIEvent?) {
print(#function) //for debugging
if var line = currentLine {
let touch = touches.first!;
let location = touch.location(in: self);
line.end = location;
finishedLines.append(line);
}
currentLine = nil;
setNeedsDisplay();
}
override func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
print(#function) //for debugging
currentLine = nil;
setNeedsDisplay();
}