์•ž ๊ธ€์—์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ ์†Œ๊ฐœํ–ˆ์ง€๋งŒ Responder Chain์€ ๊ฐ„๋‹จํ•˜๊ฒŒ ์•Œ๊ณ  ๋„˜์–ด๊ฐˆ ๋งŒํ•œ ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. ์–ด๋–ค ์‹์œผ๋กœ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์•„์•ผ ํ•˜๋Š” ์˜ค์†Œ๋ฅผ ๊ฐ์ง€ํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  ์–ด๋–ป๊ฒŒ ์ด๋ฒคํŠธ๋ฅผ ๋„˜๊ธฐ๋Š”์ง€์— ๊ด€ํ•œ ๋‚ด์šฉ์„ ์ดํ•ดํ•ด์•ผ ์‚ฌ์šฉ์ž์™€์˜ ์ œ๋Œ€๋กœ๋œ interaction์ด ์žˆ๋Š” ์•ฑ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ์ด๋ฒˆ์—๋Š” Hit Test์™€ Responder chain์— ๋Œ€ํ•ด์„œ ์ œ๋Œ€๋กœ ์•Œ์•„๋ณด๋„๋ก ํ•˜์ž. ๊ทธ๋Ÿผ ์‹œ์ž‘ํ•˜์ž.

Responder Chain

๊ฐ€์žฅ ์ƒ์œ„ (View ๊ณ„์ธต ๊ตฌ์กฐ์—์„œ ์ด๋ฒคํŠธ ๋ฐœ์ƒ์‹œ, ๊ฐ€์žฅ ์œ„์— ์žˆ๋Š” UI ์š”์†Œ) ์š”์†Œ๋กœ ์ด๋ฒคํŠธ๊ฐ€ ์ „๋‹ฌ๋˜๊ณ , ๋งŒ์•ฝ ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์ง€ ๋ชปํ•œ๋‹ค๋ฉด, ๊ทธ๋ณด๋‹ค ์ƒ์œ„์— ์žˆ๋Š” UIResponder ๊ฐ์ฒด๋กœ ์ด๋ฒคํŠธ๊ฐ€ ์ „๋‹ฌ๋˜๋Š” ๋ฐฉ์‹

์‚ฌ์šฉ์ž๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค. ๊ทธ ์ด๋ฒคํŠธ์˜ ์ข…๋ฅ˜๋Š” ๋‹ค์–‘ํ•˜๊ฒ ์œผ๋‚˜ ์ผ๋‹จ ํ„ฐ์น˜๋ฅผ ์ƒ๊ฐํ•ด๋ณด์ž. View๋Š” ๊ณ„์ธต์„ ์ด๋ฃจ๋ฉด์„œ ๊ตฌํ˜„๋˜๊ฒŒ ๋˜๋Š”๋ฐ, ํŠน์ • ์š”์†Œ๊ฐ€ ํ„ฐ์น˜๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์–ด๋–ป๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์„๊นŒ? ๊ทธ๋ฆฌ๊ณ  ํŠน์ • ์š”์†Œ๊ฐ€ ํ„ฐ์น˜๋˜์ง€ ์•Š๊ธธ ๋ฐ”๋ž€๋‹ค๋ฉด, ์‚ฌ์šฉ์ž์˜ ํ„ฐ์น˜ ์ž์ฒด๋Š” ๋ฐ”๋กœ ๋ฌด์‹œ๋˜๋Š” ๊ฒƒ์ผ๊นŒ?

์ด๋Ÿฌํ•œ ์˜๋ฌธ์— ๋Œ€ํ•œ ๋‹ต์ด Responder Chain์ด๋‹ค. ๋จผ์ € Hit test๋ฅผ ํ†ตํ•ด view ๊ณ„์ธต์—์„œ ๊ฐ€์žฅ ์ƒ์œ„์— ์žˆ๋Š” view๋ฅผ ์•Œ์•„๋‚ธ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด View๋กœ Event๊ฐ€ ์ „๋‹ฌ๋˜๊ณ , ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋กœ์ง์ด ์—†๋Š” ๊ฒฝ์šฐ, ํ•ด๋‹น View์˜ ์ƒ์œ„(superView) view๋กœ ์ด๋ฒคํŠธ๊ฐ€ ์ „๋‹ฌ๋œ๋‹ค. ์ตœ์ข…์ ์œผ๋กœ UIApplication์—์„œ ์ด๋ฒคํŠธ๊ฐ€ ์ „๋‹ฌ๋˜๊ณ , ๋ฐ›์ง€ ๋ชปํ•˜๋Š” ๊ฒฝ์šฐ ์†Œ๋ฉธ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ View๋ผ ํ†ต์นญํ–ˆ์œผ๋‚˜, ์‹ค์งˆ์ ์œผ๋กœ UIResponder ๊ฐ์ฒด๋ฅผ ์ƒ์†๋ฐ›์€ ๊ฐ์ฒด(์˜ˆ: UIView, UIViewController, UIApplication)๋ฅผ ๋งํ•œ๋‹ค.

์•Œ์•„๋‘์–ด์•ผ ํ•  ์šฉ์–ด

UIResponder

์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ์ฒด๋Š” UIResponder๋ฅผ ์ƒ์† ๋ฐ›์•„์•ผ ํ•œ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์šฐ๋ฆฌ๊ฐ€ ์•„๋Š” View ์š”์†Œ๋“ค์ด ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•ด์„œ ๋งŒ๋“ค์–ด์ ธ ์žˆ๋‹ค.

UIEvent

Event๋Š” ๋””๋ฐ”์ด์Šค์™€ ์‚ฌ์šฉ์ž๊ฐ€ ์„œ๋กœ ์†Œํ†ตํ•˜๊ธฐ ์œ„ํ•œ ์ผ์ข…์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ผ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ํ„ฐ์น˜, ๋ฆฌ๋ชจ์ปจ ๋ฒ„ํŠผ ๋ˆ„๋ฆ„, ๋ชจ์…˜ ๋“ฑ๋“ฑ ๋‹ค์–‘ํ•œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ณ  ๋””๋ฐ”์ด์Šค๋Š” ์ด๋ฅผ ์ˆ˜์‹ ํ•œ๋‹ค. ํ„ฐ์น˜๋ฅผ ์šฐ๋ฆฌ๋Š” ์•„๋งˆ ๊ฐ€์žฅ ๋งŽ์ด ๋‹ค๋ฃจ๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.

์ด ๋ถ€๋ถ„์—์„œ ์•Œ์•„๋‘์–ด์•ผ ํ•˜๋Š” ๊ฒƒ์€, ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ๊ฐ™์€ ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด์„œ ์žฌ์‚ฌ์šฉ๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ฆ‰, ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹คํ–‰๋˜๊ณ , ํŠน์ • ์ด๋ฒคํŠธ(ํ„ฐ์น˜)๊ฐ€ ์ฒ˜์Œ์œผ๋กœ ๋ฐœ์ƒ๋˜๋ฉด, ์ด ์ด๋ฒคํŠธ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  ๋‹ค์Œ ์ด๋ฒคํŠธ์—์„œ๋„ ์žฌ์‚ฌ์šฉ๋œ๋‹ค. ์ƒ์„ฑ๋œ ์ด๋ฒคํŠธ๊ฐ€ ํ„ฐ์น˜๋ผ๋ฉด, UITouch ๊ฐ์ฒด๋ฅผ ํฌํ•จํ•œ๋‹ค.

UITouch

ํ„ฐ์น˜ ์ด๋ฒคํŠธ ๋ฐœ์ƒ์‹œ, ์ด๋ฒคํŠธ ๊ฐ์ฒด์™€ ๋™์‹œ์— ๋ฐœ์ƒํ•œ ํ„ฐ์น˜์— ๊ด€ํ•œ ์ •๋ณด๋ฅผ ๋‹ด๋Š” UITouch ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. ๋‚ด๋ถ€์— ๋“ค์–ด์žˆ๋Š” ์ •๋ณด๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • ํ„ฐ์น˜๊ฐ€ ๋ฐœ์ƒํ•œ view, or window property
  • ํ„ฐ์น˜๊ฐ€ ๋ฐœ์ƒํ•œ view/window์—์„œ์˜ ์ขŒํ‘œ (func location(in: UIView?) method)
  • ํ„ฐ์น˜์˜ ๋ฐ˜์ง€๋ฆ„
  • ํ„ฐ์น˜์˜ ๊ฐ•๋„
  • ํ„ฐ์น˜ ํšŸ์ˆ˜
  • ๊ฐ™์€ ์ขŒํ‘œ์— ๋Œ€ํ•œ ํ„ฐ์น˜ ๋ฐœ์ƒ์‹œ ์ฆ๊ฐ€ํ•จ
  • ์ฒ˜์น˜๋œ ์ˆœ๊ฐ„์˜ ์‹œ๊ฐ„

UIControl

addTarget(_:action:for:) method๋กœ ์ด๋ฒคํŠธ์™€ ์•ก์…˜์„ ์—ฐ๊ฒฐํ•œ๋‹ค. UIControl์€ UIResponder ๋ฉ”์†Œ๋“œ๋ณด๋‹ค ์ƒ์œ„(๊ณ ์ˆ˜์ค€) ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์ฆ‰, ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ๋ถ„์„์ด ๋ชจ๋‘ ๋๋‚œ ์ƒํƒœ๋กœ ์ ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, UIButton์˜ .touchUpInside์˜ ๊ฒฝ์šฐ ๋ฒ„ํŠผ boundary๋‚ด์—์„œ ํ„ฐ์น˜๊ฐ€ ์‹œ์ž‘๋˜๊ณ  ๋๋‚ฌ์„ ๋•Œ๋ฅผ ์˜๋ฏธํ•˜๋Š” UIControl.Event ๊ฐ์ฒด์ด๋‹ค. ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  UIResponder๊ฐ€ ์ œ๊ณตํ•˜๋Š” method (touchesBegan, touchesEnded override)๋กœ ๊ตฌํ˜„ํ•œ๋‹ค๋ฉด ๋ช‡๋‹จ๊ณ„๋‚˜ ์ถ”๊ฐ€๋˜์–ด์•ผ ํ• ๊นŒ? ํ„ฐ์น˜ ์‹œ์ž‘, ๋์— ํ•ด๋‹นํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ overrideํ•ด์•ผ ํ•  ๊ฒƒ์ด๊ณ , target-action์œผ๋กœ ์—ฐ๊ฒฐ๋„ ํ•ด์ฃผ์–ด์•ผ ํ•  ๊ฒƒ์ด๋‹ค. ์ƒ๋‹นํžˆ ๊ท€์ฐฎ๋‹ค.

Reference