๊ธ€ ์ž‘์„ฑ์ž: ๊ฐœ๋ฐœํ•˜๋Š” ํ›ˆ์ด

UITapGestureRecognizer 

์˜ค๋Š˜์€ GestureRecognizer์˜ ์„œ๋ธŒํด๋ž˜์Šค ์ค‘ ํ•˜๋‚˜์ธ UITapGesture๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํƒญ ๋™์ž‘์„ ์ธ์‹ํ•˜๋Š” ์ž‘์—…์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์˜ค๋Š˜์˜ ๋ชฉํ‘œ๋Š” ์•„๋ž˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— UITapGestureRecognizer๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ์–ด๋–ค ์š”์†Œ๊ฐ€ ํƒญ ๋˜์—ˆ๋Š”์ง€ ํ‘œ์‹œํ•ด์ฃผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์Šคํ† ๋ฆฌ๋ณด๋“œ๋กœ ์ถ”๊ฐ€ํ•˜๊ธฐ

TapGestureRecognizer๋Š” ์Šคํ† ๋ฆฌ๋ณด๋“œ๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ๊ณ , ์ฝ”๋“œ๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋จผ์ € ๊ฐ„ํŽธํ•˜๊ฒŒ ์Šคํ† ๋ฆฌ๋ณด๋“œ๋กœ ์ž‘์—…์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ Tap Gesture Recognizer๋ฅผ ์„ ํƒํ•ด์„œ ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค.

์ •์ƒ์ ์œผ๋กœ ์ถ”๊ฐ€๊ฐ€ ๋˜์—ˆ๋‹ค๋ฉด ์™ผ์ชฝ์— Tap Gesture Recognizer๊ฐ€ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

์˜ค๋ฅธ์ชฝ ์ธ์ŠคํŽ™ํ„ฐ๋ฅผ ๋ณด๋ฉด Taps์™€ Touches์˜ ์ •๋„๋ฅผ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Taps๋Š” ๋ทฐ๊ฐ€ ๋ช‡ ๋ฒˆ ํ„ฐ์น˜ ๋˜์–ด์•ผ ์ œ์Šค์ฒ˜๊ฐ€ ์ธ์‹ํ• ์ง€๋ฅผ ์ •ํ•˜๊ณ , Touches๋Š” ๋ช‡ ๊ฐœ์˜ ์†๊ฐ€๋ฝ์œผ๋กœ ํ„ฐ์น˜ํ•ด์•ผ ์ธ์‹ํ•˜๊ฒŒ ํ• ์ง€๋ฅผ ์ •ํ•ฉ๋‹ˆ๋‹ค.

 

์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ IBAction์„ ์ถ”๊ฐ€ํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค. 

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    @IBAction func viewDidTap(_ sender: UITapGestureRecognizer) {
        print("touched")
    }
}

Tap Gesture Recognizer๊ฐ€ ์ถ”๊ฐ€๋œ ๋ทฐ์— ์ •ํ•ด์ง„ ์กฐ๊ฑด์— ๋”ฐ๋ผ ์ œ์Šค์ฒ˜๊ฐ€ ์ธ์‹๋˜๋ฉด, IBAction ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ œ์Šค์ฒ˜๊ฐ€ ์ž˜ ์ธ์‹๋˜๋Š”์ง€ ํ™•์ธํ•ด๋ณด๊ธฐ ์œ„ํ•ด์„œ ์ œ์Šค์ฒ˜๊ฐ€ ์ธ์‹๋  ๋•Œ๋งˆ๋‹ค ํ•˜๋‹จ UILabel์— ํ„ฐ์น˜๊ฐ€ ๋˜์—ˆ์Œ์„ ์•Œ๋ฆฌ๋Š” ํ…์ŠคํŠธ๋ฅผ ๋ณด์ด๋„๋ก ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ž˜ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค! ์ด์ œ ์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ชฉํ‘œ๋Œ€๋กœ ํ™”๋ฉด์˜ ๋ทฐ ์ค‘ ์–ด๋–ค ๋ทฐ๊ฐ€ ์„ ํƒ๋˜์—ˆ๋Š”์ง€๋ฅผ ์•Œ์•„๋‚ด์•ผํ•˜๋Š”๋ฐ์š”, ๊ฐ ๋ ˆ์ด๋ธ”์— ๋ชจ๋‘ ํƒญ ์ œ์Šค์ฒ˜๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์ง€๋งŒ hitTest ๋ฉ”์„œ๋“œ๋ฅผ ์†Œ๊ฐœํ•  ๊ฒธ hitTest()๋ฅผ ์ด์šฉํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

hitTest(_:with:)

๐Ÿ’ก Returns the farthest descendant of the receiver in the view hierarchy (including itself) that contains a specified point.

 

hitTest ๋ฉ”์„œ๋“œ๋Š” ์–ด๋–ค ์ขŒํ‘œ๊ฐ€ ์ „๋‹ฌ๋˜์—ˆ์„ ๋•Œ ํ•ด๋‹น ์ขŒํ‘œ๋ฅผ ํฌํ•จํ•˜๋Š” ์ตœ์ƒ๋‹จ(์‚ฌ์šฉ์ž์™€ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด)์— ์œ„์น˜ํ•œ ๋ทฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ž…๋‹ˆ๋‹ค. UITapGesture๋Š” location ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ์˜ ์ขŒํ‘œ๊ฐ€ ์ „๋‹ฌ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ด ์ขŒํ‘œ๋ฅผ hitTest ํ•ด์„œ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ด์šฉํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var resultLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    @IBAction func viewDidTap(_ sender: UITapGestureRecognizer) {
        resultLabel.text = (self.view.hitTest(sender.location(in: self.view), with: nil) as? UILabel)?.text ?? "NONE"
        resultLabel.sizeToFit()
    }
}

IBAction์—์„œ ์ „๋‹ฌ๋˜๋Š” ์ขŒํ‘œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ hitTest๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ , ๋ฐ˜ํ™˜๋œ ๋ทฐ๊ฐ€ UIView๋ผ๋ฉด ํ…์ŠคํŠธ๋ฅผ ํ•˜๋‹จ์˜ UILabel์˜ ํ…์ŠคํŠธ๋กœ ์„ค์ •ํ•ด์ฃผ๋„๋ก ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ ์ด์ œ ํ…Œ์ŠคํŠธํ•ด๋ณผ๊นŒ์š”?

 

์ž˜ ๋™์ž‘ํ•˜๋„ค์š”! ์ด๋ ‡๊ฒŒ ์Šคํ† ๋ฆฌ๋ณด๋“œ๋ฅผ ํ†ตํ•ด Tap Gesture Recognizer๋ฅผ ์›ํ•˜๋Š” ๋ทฐ์— ์ถ”๊ฐ€ํ•˜๊ณ  IBAction์„ ์ •์˜ํ•ด ์›ํ•˜๋Š” ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ๋กœ ์ถ”๊ฐ€ํ•˜๊ธฐ

์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ์ถ”๊ฐ€ํ–ˆ๋˜ Tap Gesture Recognizer๋ฅผ ์‚ญ์ œํ•˜๊ณ  ๋‹ค์‹œ ์ž‘์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. TapGestureRecognizer๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ์œ„ํ•ด์„œ๋Š” UIGestureRecognizerDelegate๋ฅผ ์ฑ„ํƒํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ œ์Šค์ฒ˜์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์œ„์ž„๋ฐ›์•„ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ์ž…๋‹ˆ๋‹ค.

extension ViewController: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        return true
    }
}
class ViewController: UIViewController {
    @IBOutlet weak var resultLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let tapGestureRecognizer = UITapGestureRecognizer()
        tapGestureRecognizer.delegate = self
        self.view.addGestureRecognizer(tapGestureRecognizer)
    }
}

๊ทธ๋ฆฌ๊ณ  viewDidLoad์— Tap Gesture Recognizer๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋Š” ์ž‘์—…์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

 

์ด์ œ ํ”„๋กœํ† ์ฝœ์„ UITapGestureRecognizer์˜ gestureRecognizer ๋ฉ”์„œ๋“œ์— ์ •์˜ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ์ •์˜ํ–ˆ๋˜ IBAction์˜ ๋กœ์ง์„ ๊ทธ๋Œ€๋กœ ์˜ฎ๊ฒจ์˜ค๋ฉด ๋˜๊ฒ ์ฃ ? ์ด๋ฒˆ์—๋Š” sender๋ผ๋Š” ์ธ์ž๊ฐ€ ์—†์ง€๋งŒ touch ์ธ์ž๋ฅผ ํ†ตํ•ด location์„ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

extension ViewController: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        resultLabel.text = (self.view.hitTest(touch.location(in: self.view), with: nil) as? UILabel)?.text ?? "NONE"
        resultLabel.sizeToFit()
        return true
    }
}

๊ทธ๋Ÿผ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๋Š”์ง€ ํ…Œ์ŠคํŠธํ•ด๋ณด์ฃ !

์Šคํ† ๋ฆฌ๋ณด๋“œ๋กœ ์ถ”๊ฐ€ํ–ˆ์„ ๋•Œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ž˜ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” ํƒญ ์ด๋ฒคํŠธ๋ฅผ ์ธ์‹ํ•˜๋Š” UITapGestureRecognizer๋ฅผ ์Šคํ† ๋ฆฌ๋ณด๋“œ๋กœ, ์ฝ”๋“œ๋กœ ์ถ”๊ฐ€ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ํƒญ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ€์žฅ ๋งŽ์ด ํ•˜๋Š” ๋™์ž‘์ด๋‹ˆ ์–ด๋””์„œ๋“  ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค!