Do it! 스위프트로 아이폰 앱 만들기
17장 탭과 터치 이용해 스케치 앱 만들기
- 빈 스토리보드에 Horizontal Stack View 배치하기
- 세로 스택 뷰 안에 Image View 배치하기
- 이미지 뷰 아래에 Button 배치하기
- [Add New Constraints] -> [Height] = 40 으로 설정하기
- 이미지 뷰에 대한 아웃렛 변수 추가하기
- 버튼에 대한 액션 함수 추가하기
import UIKit
class ViewController: UIViewController {
@IBOutlet var imgView: UIImageView!
var lastPoint: CGPoint!
var lineSize: CGFloat = 2.0
var lineColor = UIColor.red.cgColor
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func clearImageView(_ sender: UIButton) {
imgView.image = nil
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
}
}
- 변수 추가하기
- 버튼의 액션 함수 작성하기
- 터치 이벤트 메소드 재정의하기
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first! as UITouch
lastPoint = touch.location(in: imgView)
}
터치가 시작되었을 때의 메소드
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
UIGraphicsBeginImageContext(imgView.frame.size)
UIGraphicsGetCurrentContext()?.setStrokeColor(lineColor)
UIGraphicsGetCurrentContext()?.setLineCap(CGLineCap.round)
UIGraphicsGetCurrentContext()?.setLineWidth(lineSize)
let touch = touches.first! as UITouch //터치 이벤트 가져오기
let currPoint = touch.location(in: imgView) //터치된 위치 가져오기
imgView.image?.draw(in: CGRect(x: 0, y: 0, width: imgView.frame.size.width, height: imgView.frame.size.height))
UIGraphicsGetCurrentContext()?.move(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
UIGraphicsGetCurrentContext()?.addLine(to: CGPoint(x: currPoint.x, y: currPoint.y))
UIGraphicsGetCurrentContext()?.strokePath()
imgView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
lastPoint = currPoint
}
터치된 채로 움직일 때의 메소드
- imgView.image?.draw
- touchesMoved 메소드는 터치 상태로 움직이는 동안 지속적으로 호출된다.
- 즉 UIGraphicsBeginImageContext 의 생성 및 종료가 지속적으로 반복되는 것이다.
- 때문에 이전에 이미지 뷰에 그려진 이미지를 draw 메소드를 통해 current context 에 저장해야한다.
- 그렇지 않으면 터치 경로대로 그림이 업데이트되지 않는다.
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
UIGraphicsBeginImageContext(imgView.frame.size)
UIGraphicsGetCurrentContext()?.setStrokeColor(lineColor)
UIGraphicsGetCurrentContext()?.setLineCap(CGLineCap.round)
UIGraphicsGetCurrentContext()?.setLineWidth(lineSize)
imgView.image?.draw(in: CGRect(x: 0, y: 0, width: imgView.frame.size.width, height: imgView.frame.size.height))
UIGraphicsGetCurrentContext()?.move(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
UIGraphicsGetCurrentContext()?.addLine(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
UIGraphicsGetCurrentContext()?.strokePath()
imgView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
터치가 끝났을 때의 메소드
override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
if motion == .motionShake {
imgView.image = nil
}
}
디바이스를 흔들었을 때 스케치가 지워지도록 하는 메소드
import UIKit
class ViewController: UIViewController {
@IBOutlet var imgView: UIImageView!
var lastPoint: CGPoint!
var lineSize: CGFloat = 2.0
var lineColor = UIColor.red.cgColor
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func clearImageView(_ sender: UIButton) {
imgView.image = nil
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first! as UITouch
lastPoint = touch.location(in: imgView)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
UIGraphicsBeginImageContext(imgView.frame.size)
UIGraphicsGetCurrentContext()?.setStrokeColor(lineColor)
UIGraphicsGetCurrentContext()?.setLineCap(CGLineCap.round)
UIGraphicsGetCurrentContext()?.setLineWidth(lineSize)
let touch = touches.first! as UITouch //터치 이벤트 가져오기
let currPoint = touch.location(in: imgView) //터치된 위치 가져오기
imgView.image?.draw(in: CGRect(x: 0, y: 0, width: imgView.frame.size.width, height: imgView.frame.size.height))
UIGraphicsGetCurrentContext()?.move(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
UIGraphicsGetCurrentContext()?.addLine(to: CGPoint(x: currPoint.x, y: currPoint.y))
UIGraphicsGetCurrentContext()?.strokePath()
imgView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
lastPoint = currPoint
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
UIGraphicsBeginImageContext(imgView.frame.size)
UIGraphicsGetCurrentContext()?.setStrokeColor(lineColor)
UIGraphicsGetCurrentContext()?.setLineCap(CGLineCap.round)
UIGraphicsGetCurrentContext()?.setLineWidth(lineSize)
imgView.image?.draw(in: CGRect(x: 0, y: 0, width: imgView.frame.size.width, height: imgView.frame.size.height))
UIGraphicsGetCurrentContext()?.move(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
UIGraphicsGetCurrentContext()?.addLine(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
UIGraphicsGetCurrentContext()?.strokePath()
imgView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
if motion == .motionShake {
imgView.image = nil
}
}
}
import UIKit
class ViewController: UIViewController {
@IBOutlet var imgView: UIImageView!
@IBOutlet var widthTf: UITextField!
var lastPoint: CGPoint!
var lineSize: CGFloat = 2.0
var lineColor = UIColor.black.cgColor
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
widthTf.text = String(Int(lineSize))
}
@IBAction func btnBlack(_ sender: UIButton) {
lineColor = UIColor.black.cgColor
}
@IBAction func btnRed(_ sender: UIButton) {
lineColor = UIColor.red.cgColor
}
@IBAction func btnGreen(_ sender: UIButton) {
lineColor = UIColor.green.cgColor
}
@IBAction func btnBlue(_ sender: UIButton) {
lineColor = UIColor.blue.cgColor
}
@IBAction func clearImageView(_ sender: UIButton) {
imgView.image = nil
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first! as UITouch
lastPoint = touch.location(in: imgView)
lineSize = CGFloat(Int(widthTf.text!)!)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
UIGraphicsBeginImageContext(imgView.frame.size)
UIGraphicsGetCurrentContext()?.setStrokeColor(lineColor)
UIGraphicsGetCurrentContext()?.setLineCap(CGLineCap.round)
UIGraphicsGetCurrentContext()?.setLineWidth(lineSize)
let touch = touches.first! as UITouch //터치 이벤트 가져오기
let currPoint = touch.location(in: imgView) //터치된 위치 가져오기
imgView.image?.draw(in: CGRect(x: 0, y: 0, width: imgView.frame.size.width, height: imgView.frame.size.height))
UIGraphicsGetCurrentContext()?.move(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
UIGraphicsGetCurrentContext()?.addLine(to: CGPoint(x: currPoint.x, y: currPoint.y))
UIGraphicsGetCurrentContext()?.strokePath()
imgView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
lastPoint = currPoint
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
UIGraphicsBeginImageContext(imgView.frame.size)
UIGraphicsGetCurrentContext()?.setStrokeColor(lineColor)
UIGraphicsGetCurrentContext()?.setLineCap(CGLineCap.round)
UIGraphicsGetCurrentContext()?.setLineWidth(lineSize)
imgView.image?.draw(in: CGRect(x: 0, y: 0, width: imgView.frame.size.width, height: imgView.frame.size.height))
UIGraphicsGetCurrentContext()?.move(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
UIGraphicsGetCurrentContext()?.addLine(to: CGPoint(x: lastPoint.x, y: lastPoint.y))
UIGraphicsGetCurrentContext()?.strokePath()
imgView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
if motion == .motionShake {
imgView.image = nil
}
}
}
곽철이 그려줘요