I\'m trying to make a drawing app. I have a single custom UIView:
class DrawView: UIView {
var touch : UITouch!
var lastPoint : CGPoint!
var currentPoint : CGPo
Two things:
Calling self.setNeedsDisplay
doesn't immediately call drawRect
. It just sets a flag so that drawRect
will be called in the near future. Since you set lastPoint
to currentPoint
right after that, when drawRect
is called lastPoint
is always equal to currentPoint
.
drawRect
redraws the entire view every time it is called, so at most you'd only ever see the most recent line. If you fixed problem 1, you'd have a short line following your finger instead of a dot. If you want to see the whole trail, you'll need to store the points in an array that is a property of your view, and then draw lines to connect all of the points in drawRect
.
marcomoreira92 and Keuha's version worked for me, but I don't like to use indices that much. Thus here is an alternative version, which was tested in Swift 4.2:
class DrawView: UIView {
var lineArray: [[CGPoint]] = [[CGPoint]]()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let firstPoint = touch.location(in: self)
lineArray.append([CGPoint]())
lineArray[lineArray.count - 1].append(firstPoint)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let currentPoint = touch.location(in: self)
lineArray[lineArray.count - 1].append(currentPoint)
setNeedsDisplay()
}
override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
context?.setLineWidth(5)
context?.setStrokeColor(UIColor.black.cgColor)
context?.setLineCap(.round)
for line in lineArray {
guard let firstPoint = line.first else { continue }
context?.beginPath()
context?.move(to: firstPoint)
for point in line.dropFirst() {
context?.addLine(to: point)
}
context?.strokePath()
}
}
}
Hi i make some simple changes and fixed your code, hope it helps someone in the future (code it's updated for Swift 3) :
class DrawView: UIView {
var touch : UITouch!
var lineArray : [[CGPoint]] = [[CGPoint]()]
var index = -1
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
touch = touches.first! as UITouch
let lastPoint = touch.location(in: self)
index += 1
lineArray.append([CGPoint]())
lineArray[index].append(lastPoint)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
touch = touches.first! as UITouch
let currentPoint = touch.location(in: self)
self.setNeedsDisplay()
lineArray[index].append(currentPoint)
}
override func draw(_ rect: CGRect) {
if(index >= 0){
let context = UIGraphicsGetCurrentContext()
context!.setLineWidth(5)
context!.setStrokeColor((UIColor(red:0.00, green:0.38, blue:0.83, alpha:1.0)).cgColor)
context!.setLineCap(.round)
var j = 0
while( j <= index ){
context!.beginPath()
var i = 0
context?.move(to: lineArray[j][0])
while(i < lineArray[j].count){
context?.addLine(to: lineArray[j][i])
i += 1
}
context!.strokePath()
j += 1
}
}
}
}