[iOS]UIView에서 Touch event 관리하기

신용철·2020년 10월 26일
0

iOS_View

목록 보기
9/11

UIView는 기본적으로 touch 이벤트를 관리할 수 있게 되어있습니다. 이번 포스트에서는 UIView의 touch이벤트를 관리할 수 있는 method에는 무엇이 있고 어떤 식으로 활용할 수 있는지 알아보겠습니다.

1. Touch event관리 method

  • touchesBegan(touches:event:) : 이 method는 사용자가 view를 터치하면 호출됩니다.
  • 첫 번째 Parameter로 전달되는 Set<UITouch>는 touch된 좌표값 등 touch와 관련된 다양한 속성을 제공합니다. 또한, multi touch 이벤트가 발생할 수 있기 때문에 Set으로 관리됩니다.
  • 아래와 같이 .location을 이용하여 터치되는 point를 CGPoint타입으로 전달할 수 있습니다.
 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
 
      var touchPoint: [CGPoint] = []
      for point in touches {
      //open func location(in view: UIView?) -> CGPoint
         touchPoint.append.point.location(in: self)
         }
   }
  • touchesEnded(touches:event:): 이 method는 사용자가 view에서 손가락을 떼면 호출됩니다.

  • touchesCancelled(touches:event:): 이 method는 사용자가 touch를 하고 있는 중에 다른 event가 발생하여 touch를 강제로 종료시킬 때 호출됩니다. 예를 들면 갑자기 전화가 오거나 화면이 전환되는 경우입니다.

2. Draw(rect:)와 setNeedsDisplay()

  • UIView는 생성되어 화면에 표시되기 전에draw(_ rect: CGRect)를 호출하여 view의 생성 조건을 반영합니다. 즉, 이 methode의 body부분에 code를 구현하면 view가 그려질 때 반영됩니다.

  • View는 drawing 성능을 향상시키기 위해(resource 절약을 위해) bitmap 캐싱을 이용합니다. view가 표시될 때마다 새로 drawing을 하지않고 view에 표시될 contents를 캐싱해두었다가 재활용하는 방식입니다. 그러나 view에 event가 발생할 때마다 캐싱된 contents만을 사용하면 event발생에 따른 view의 변화를 반영할 수 없습니다. 이럴 때 setNeedsDisplay()를 호출하여 draw(_ rect: CGRect)를 다시 호출할 수 있습니다. tableView의 reloadData()를 떠올리면 이해가 수월합니다.

  • setNeedsDisplay()사용 예시: touch이벤트가 발생할 때 해당 point에 어떤 이미지가 보였다가 손을 떼면 사라지는 기능을 view에 반영한다고 하면, touch이벤트가 발생하는 순간 해당 좌표에 image를 표시해야합니다. 이 때 "draw method에 touch가 발생할 경우에는 이미지를 추가한다"는 code를 작성하고 touch가 발생하는 순간 setNeedsDisplay()를 호출하여 drawing을 다시 실행하면 view에 이미지가 추가 됩니다.

3. 활용 예제

  • 여기서 구현한 예제는 view에 터치이벤트가 발생하면 해당 좌표에 곰발바닥이 나타났다가 touch가 종료되면 사라지는 코드입니다. (출저: https://kxcoding.com)
  • 코드작성 논리는 아래와 같습니다.

    1) touch event 발생
    2) touch 좌표 계산하여 class top level 프로퍼티에 저장
    3) setNeedsDisplay() 호출
    4) redrawing
    5) draw(_ rect: CGRect) 실행
    6) 곰발바닥 표시된 view drawing
    7) touch 종료
    8) setNeedsDisplay() 호출
    9) redrawing
    10) draw(_ rect: CGRect) 실행
    11) 곰발바닥 표시해제된 view drawing"

  • 예제 코드
class InteractionViewController: UIViewController {
  
   @IBOutlet weak var touchView: TouchView!
    
   override func viewDidLoad() {
      super.viewDidLoad()
      
   touchView.isUserInteractionEnabled = true
   touchView.isMultipleTouchEnabled = true
   }   
}

class TouchView: UIView {
   let pawImage = UIImage(named: "paw")
   var points = [CGPoint]()
   
   override func draw(_ rect: CGRect) {
      super.draw(rect)
      
      for pt in points {
         pawImage?.draw(at: pt)
      }
   }
   
   override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
      
      for t in touches {
         let pt = t.location(in: self)
         
         points.append(pt.applying(CGAffineTransform(translationX: -32, y: -32)))
      }
      
      setNeedsDisplay()
   }
   
   override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
      points.removeAll()
      setNeedsDisplay()
   }
   
   override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
      points.removeAll()
      setNeedsDisplay()
   }
}
profile
iOS developer

0개의 댓글