Potato
์•ˆ๋…•ํ•˜์„ธ์š”, ๊ฐ์žก๋‹ˆ๋‹ค?๐Ÿฅ” ^___^ ๐Ÿ˜บ github ๋ฐ”๋กœ๊ฐ€๊ธฐ ๐Ÿ‘‰๐Ÿป

Swift/UIKit

[UIKit] UIResponder (feat. Responder, Responder Chain, FirstResponder)

๊ฐ์ž ๐Ÿฅ” 2022. 7. 7. 10:55
๋ฐ˜์‘ํ˜•

์˜ค๋Š˜๋ถ€ํ„ฐ ๋ฏธ๋ผํด ๋ชจ๋‹ ์‹œ๊ฐ„์— 1์ผ 1์œ ์•„์ดํ‚ท ํฌ์ŠคํŒ…์„ ํ•ด๋ณด๋ ค๊ณ ํ•œ๋‹ค. ๊ตฌํ˜„์œ„์ฃผ์˜ ๊ณต๋ถ€๋ฅผ ํ•˜๋‹ค๋ณด๋‹ˆ, ๊ธฐ์ดˆ์ง€์‹์ด ๋„ˆ๋ฌด ๋ถ€์กฑํ•˜๋‹ค๊ณ  ๋Š๊ปด์กŒ๊ณ , UIKit์˜ ๊ตฌ์กฐ๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ํŒŒ์•…ํ•˜๊ณ  ์‹ถ์–ด์„œ ์‹œ์ž‘! 

 

๐Ÿ”ต UIResponder

xcodeํ”„๋กœ์ ํŠธ๋ฅด ๋งŒ๋“ค๋ฉด AppDelegate์™€ SceneDelegate๋ฅผ ์ฒ˜์Œ์œผ๋กœ ์ ‘ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด ๋‘๊ฐœ์˜ ํด๋ž˜์Šค๋Š” ๋™์ผํ•˜๊ฒŒ "UIResponder"๋ฅผ ์ƒ์†๋ฐ›๋Š”๋‹ค.

์šฐ์„  ๊ณต์‹๋ฌธ์„œ๊ฐ€ ์ •์˜ํ•œ ๊ฐœ๋…๋ถ€ํ„ฐ ์ฐจ๊ทผ์ฐจ๊ทผ ์ฝ์–ด๋ณด์ž.

https://developer.apple.com/documentation/uikit/uiresponder

 

Apple Developer Documentation

 

developer.apple.com

An abstract interface for responding to and handling events.

์ด๋ฒคํŠธ์— ์‘๋‹ตํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ถ”์ƒ ์ธํ„ฐํŽ˜์ด์Šค์ด๋‹ค.

Responder objects—that is, instances of  UIResponder —constitute the event-handling backbone of a UIKit app. Many key objects are also responders, including the UIApplication object, UIViewController objects, and all UIView objects (which includes UIWindow). As events occur, UIKit dispatches them to your app's responder objects for handling.

Responder ๊ฐ์ฒด๋Š” UIResponder์˜ ์ธ์Šคํ„ด์Šค์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ์ธ์Šคํ„ด์Šค๊ฐ€ UIKit์—์„œ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ์˜ ์ค‘์ถ”์—ญํ• ์„ ํ•œ๋‹ค. UIKit์˜ ๋งŽ์€ ๊ฐ์ฒด๋“ค, UIApplication, UIViewController, UIView๊ฐ™์€ ๊ฐ์ฒด๋“ค์ด ๋ชจ๋‘ Responder์ด๊ธฐ๋„ ํ•˜๋‹ค. ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด UIKit์€ ์ด๋ฒคํŠธ Responder๊ฐ์ฒด์—๊ฒŒ ์ „๋‹ฌํ•ด์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค. 

There are several kinds of events, including touch events, motion events, remote-control events, and press events. To handle a specific type of event, a responder must override the corresponding methods. For example, to handle touch events, a responder implements the touchesBegan(_:with:), touchesMoved(_:with:), touchesEnded(_:with:), and touchesCancelled(_:with:) methods. In the case of touches, the responder uses the event information provided by UIKit to track changes to those touches and to update the app's interface appropriately.

ํ™”๋ฉด์„ ํ„ฐ์น˜ํ•˜๊ฑฐ๋‚˜ ์ œ์Šค์ณ๋ฅผ ์ทจํ•˜๋Š” ๋“ฑ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ด๋ฒคํŠธ๊ฐ€ ์žˆ๋‹ค. ์–ด๋–ค ํŠน์ •ํ•œ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด ๋ฐ˜๋“œ์‹œ ํ•ด๋‹น ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ Responder๊ฐ์ฒด๊ฐ€ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•ด์„œ ๋‚ด์šฉ์„ ๊ตฌํ˜„ํ•œ๋‹ค. touchesBegan, touchesMoved ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์™€ UIView์—์„œ ์ •์˜ํ•  ์ˆ˜ ์žˆ์—ˆ๋˜ ๊ฒƒ๋„ ๋ชจ๋‘ ์ด ๊ฐ์ฒด๋“ค์ด Responder์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด ํ„ฐ์น˜์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด responder๊ฐ์ฒด๋Š” UIKit์—์„œ ์ œ๊ณตํ•˜๋Š” ์ •๋ณด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์•ฑ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.

In addition to handling events, UIKit responders also manage the forwarding of unhandled events to other parts of your app. If a given responder does not handle an event, it forwards that event to the next event in the responder chain. UIKit manages the responder chain dynamically, using predefined rules to determine which object should be next to receive an event. For example, a view forwards events to its superview, and the root view of a hierarchy forwards events to its view controller.

์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ ๋ฟ๋งŒ์•„๋‹ˆ๋ผ UIKit ์˜ responder๋“ค์€ ์ž์‹ ์ด ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š” ์ด๋ฒคํŠธ๋ฅผ ์•ฑ์˜ ๋‹ค๋ฅธ ์š”์†Œ๋“ค์—๊ฒŒ ์ „๋‹ฌํ•˜๋Š” ์—ญํ• ๋„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ๋งŒ์•ฝ์— ์–ด๋–ค responder๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ด ๊ฐ์ฒด๊ฐ€ Responder Chain์˜ ๋‹ค์Œ responder์—๊ฒŒ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค. Responder chain์€ UIkit์— ์˜ํ•ด ๋ฏธ๋ฆฌ ์ •ํ•ด์ง„ ๊ทœ์น™์—ใ„ท ๋”ฐ๋ผ ๋™์ ์œผ๋กœ ๊ด€๋ฆฌ๋œ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด View๋Š” ์ž์‹ ์˜ super view์—๊ฒŒ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•˜๊ณ , ์ตœ์ƒ์œ„์— ์žˆ๋Š” view๋Š” ViewController์—๊ฒŒ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

Responders process UIEvent objects but can also accept custom input through an input view. The system's keyboard is the most obvious example of an input view. When the user taps a UITextField and UITextView object onscreen, the view becomes the first responder and displays its input view, which is the system keyboard. Similarly, you can create custom input views and display them when other responders become active. To associate a custom input view with a responder, assign that view to the inputView property of the responder.

Responder ๊ฐ์ฒด๋“ค์€ UIEvent ๊ฐ์ฒด๋“ค์„ ์ฒ˜๋ฆฌํ•˜์ง€๋งŒ input view๋ฅผ ํ†ตํ•ด์„œ ์ปค์Šคํ…€ ์ž…๋ ฅ์„ ๋ฐ›์„ ์ˆ˜๋„ ์žˆ๋‹ค. ๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ custom input ์˜ˆ์‹œ๋Š” ํ‚ค๋ณด๋“œ์ด๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ํ™”๋ฉด์— ์žˆ๋Š” UITextField์™€ UITextView์„ ํƒญํ•˜๋ฉด, ํ•ด๋‹น ๋ทฐ๋Š” First Responder๊ฐ€ ๋˜์–ด ์ž…๋ ฅ๋ทฐ (ํ‚ค๋ณด๋“œ)๋ฅผ ํ‘œ์‹œํ•œ๋‹ค. ์ด์ฒ˜๋Ÿผ ๊ฐœ๋ฐœ์ž๋Š” ์ปค์Šคํ…€ ์ž…๋ ฅ๋ทฐ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์–ด๋–ค responder๊ฐ์ฒด๊ฐ€ ํ™œ์„ฑํ™”๋˜๋ฉด ํ™”๋ฉด์— ํ‘œ์‹œ๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๐Ÿ”น UIResponder ์˜ ์—ญํ•  ์ •๋ฆฌ

๊ทธ๋ž˜์„œ ์š”์•ฝํ•ด๋ณด๋ฉด, ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  1. UIResponder๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด, ์ฒ˜๋ฆฌํ•ด์„œ ๋‚ด์šฉ์„ ๊ตฌํ˜„ํ•˜๋Š” ์ผ์„ ์ฃผ๋กœ ๋งก์•„์„œ ํ•œ๋‹ค.
  2. ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ผ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ์ž์‹ ์ด ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š” ์ด๋ฒคํŠธ๋Š” Responder Chain ๊ทœ์น™์— ์˜ํ•ด ์ •ํ•ด์ง„ ๋‹ค์Œ responder์—๊ฒŒ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์—ญํ• ๋„ ํ•œ๋‹ค.
  3. input view๋ฅผ ํ†ตํ•ด์„œ ์ปค์Šคํ…€ ์ž…๋ ฅ์„ ๋ฐ›์„ ์ˆ˜๋„ ์žˆ๋‹ค.

๊ณต์‹๋ฌธ์„œ๋ฅผ ๋ณด๋ฉด์„œ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š”๊ฒŒ UIResponder์ธ๊ฑด ์•Œ๊ฒ ๋‹ค. ๊ทผ๋ฐ ๋ชจ๋ฅด๋Š”๊ฐœ๋…์ด ์„ธ๊ฐ€์ง€ ๋‚˜์™€์„œ 'ํŒŒ๋ž€์ƒ‰'๊ธ€์”จ๋กœ ํ‘œ์‹œํ•ด๋’€๋‹ค. ํ•ด๋‹น ๊ฐœ๋…๋“ค์„ ์ฐจ๊ทผ์ฐจ๊ทผ ์•Œ์•„๋ณด๋ฉด์„œ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ์ดํ•ดํ•ด๋ณด์ž.

 

๐Ÿ”ต Responder ๊ฐ์ฒด

Responder๋Š” ์ด๋ฒคํŠธ๋ฅผ ํ•ธ๋“ค๋งํ•˜๊ณ  ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด์ด๋‹ค. ๋ชจ๋“  Responder๊ฐ์ฒด๋Š” UIResponder์—์„œ ์ƒ์†๋œ ํด๋ž˜์Šค๋“ค์˜ ์ธ์Šคํ„ด์Šค์ด๋‹ค. ๊ทธ๋‹ˆ๊นŒ UIResponder ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋“ค์„ Responder ๊ฐ์ฒด๋ผ๊ณ  ํ•œ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ UIView, UIView์˜ ์„œ๋ธŒํด๋ž˜์Šค์ธ UIWindow, UIViewController, UIApplication ๋“ฑ์ด ์žˆ๋‹ค.

์œ„์—์„œ ์„ค๋ช…ํ–ˆ๋“ฏ, Responder๋Š” ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌ ๋ฐ›์•˜์œผ๋ฉด ๋ฐ˜๋“œ์‹œ ๊ทธ๊ฒƒ์„ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ Resonder๊ฐ์ฒด๋กœ ๋„˜๊ฒจ์ฃผ์–ด์•ผํ•œ๋‹ค. ์•ฑ์ด ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌ๋ฐ›์•˜์„ ๋•Œ, UIKit์€ ์ž๋™์œผ๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ์— ๊ฐ€์žฅ ์ ์ ˆํ•œ Responder ๊ฐ์ฒด๋กœ ์ด๋ฒคํŠธ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

์—ฌ๊ธฐ์„œ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ์— ๊ฐ€์žฅ ์ ์ ˆํ•œ Resonder๊ฐ์ฒด๋ฅผ FirstResponder๋ผ๊ณ  ํ•œ๋‹ค!

 

๐Ÿ”ต Responder Chain

์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ์ด๋ฒคํŠธ๋“ค์€ ๋ฆฌ์Šคํฐ๋”์—์„œ ๋‹ค๋ฅธ ๋ฆฌ์Šคํฐ๋”๋กœ Active Responder Chain์„ ๋”ฐ๋ผ ์ด๋™ํ•œ๋‹ค. resopnder chain์€ ์•ฑ์˜ responder ๊ฐ์ฒด์— ๋”ฐ๋ผ ๋™์ ์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค. (๋งค๋ฒˆ ๊ฐ™์ง€๋Š” ์•Š๋‹ค๋Š” ์–˜๊ธฐ!)

์•„๋ž˜ ๊ทธ๋ฆผ์€ UILabel, UITextField, UIButton ๊ทธ๋ฆฌ๊ณ  ๋‘ ๊ฐœ์˜ ๋ฐฑ๊ทธ๋ผ์šด๋“œ View๋กœ UI๋ฅผ ๊ตฌ์„ฑํ•œ responder๋“ค์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ทธ๋ฆผ์ด๋‹ค. ๊ทธ๋ฆผ์—์„œ๋Š” ํ™”์‚ดํ‘œ๋ฅผ ํ†ตํ•ด responder ๊ฐ์ฒด๋“ค์ด responder chain์„ ๊ตฌ์„ฑํ•œ๋‹ค.

ํ™”์‚ดํ‘œ๋ฐฉํ–ฅ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ์ด๋ฒคํŠธ๋“ค์ด ์ „๋‹ฌ๋œ๋‹ค๊ณ  ์ดํ•ดํ•˜๋ฉด ๋œ๋‹ค.

๋งŒ์•ฝ UIButton์ด ์ „๋‹ฌ๋ฐ›์€ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, UIKit์€ Button์˜ super view์ธ UIView๋กœ ์šฐ์„  ์ „๋‹ฌํ•œ๋‹ค. ์ด UIView์—์„œ๋„ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, UIView์˜ ๋ฃจํŠธ๋ทฐ์ธ UIView(๋‘๋ฒˆ์งธ ์ฒญ๋ก์ƒ‰!)์œผ๋กœ ์ „๋‹ฌ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ๋„ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์ด view์™€ ์—ฐ๊ฒฐ๋œ ViewController๋ฅผ ๊ฑฐ์ณ UIWindow๊นŒ์ง€ ์—ฐ์‡„์ ์œผ๋กœ ์ „๋‹ฌ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ๋„ ์ด๋ฒคํŠธ๊ฐ€ ์ฒ˜๋ฆฌ๋˜์ง€ ๋ชปํ•˜๋ฉด, UIApplication๊นŒ์ง€ ์˜ฌ๋ผ๊ฐ€์„œ ์ฒ˜๋ฆฌ๋  ์ˆ˜๋„ ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋„ ์ด๋ฒคํŠธ๊ฐ€ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์‚ญ์ œ๋œ๋‹ค.

(UIView์˜ ์ •์˜๋ฅผ ์‚ดํŽด๋ณด๋ฉด, UIResponder๋ฅผ ์ƒ์†๋ฐ›๊ณ  ์žˆ๋‹ค. UITextField๋Š” UIControl์„ ์ƒ์†๋ฐ›๊ณ ์žˆ๋Š”๋ฐ, UIContrl์ด UIResponder๋ฅผ ์ƒ์†๋ฐ›๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ„์˜ Responder chain์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.)

์•„๋ž˜ Method๋“ค์€ responder chain์„ ๊ด€๋ฆฌํ•ด์ฃผ๋Š” ๋ฉ”์†Œ๋“œ๋“ค์ด๋‹ค. ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๋ช…ํ•˜์ž๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ง€๋งŒ, ๋” ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‚˜์ค‘์— ๋‹ค๋ค„๋ณด๋„๋ก ํ•˜์ž.

  • becomeFirstResponder : window์˜ ์ฒซ๋ฒˆ์งธ responder๋กœ ๋งŒ๋“ค๊ธฐ์œ„ํ•ด ์‚ฌ์šฉ
  • resignFirstResponder : window์˜ ์ตœ์ดˆ responder๋กœ์„œ ์ƒํƒœ๋ฅผ ์–‘๋„ํ•˜๋„๋ก ์š”์ฒญ๋ฐ›์•˜์Œ์„ ์•Œ๋ฆฐ๋‹ค. (์ฆ‰, UITextField์—์„œ resignFirstResponder()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, ํ‚ค๋ณด๋“œ๊ฐ€ ์‚ฌ๋ผ์ง€๋Š”๊ฒŒ ๊ทธ ์˜ˆ์‹œ์ด๋‹ค.)

 

๐Ÿ”น ์ด๋ฒคํŠธ์˜ First Responder ๊ฒฐ์ •ํ•˜๊ธฐ

๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ UIKit์€ firstResponder๋ฅผ ์„ค์ •ํ• ๊นŒ? UIKit์€ '๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ์˜ ํƒ€์ž…'์„ ๊ธฐ์ค€์œผ๋กœ firstResponder๋ฅผ ์„ค์ •ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” event ๋Š” UIEvent์˜ ์ธ์Šคํ„ด์Šค์ธ๋ฐ, ์—ฌ๋Ÿฌ type์˜ ์ด๋ฒคํŠธ๊ฐ€ ์กด์žฌํ•œ๋‹ค.

https://developer.apple.com/documentation/uikit/uievent/1613840-type

 

Apple Developer Documentation

 

developer.apple.com

์—ฌ๊ธฐ์„œ ๊ฐ€์žฅ ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ๋Š” ํ„ฐ์น˜ ์ด๋ฒคํŠธ์ด๋‹ค. (press๋Š” ๋ฌผ๋ฆฌ ํ‚ค์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ, remote-control์€ ํ—ค๋“œํฐ ๋“ฑ ์™ธ๋ถ€ ๊ธฐ๊ธฐ์—์„œ ๋ˆ„๋ฅด๋Š” ๋ฒ„ํŠผ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ, editing menu๋Š” ํ•ธ๋“œํฐ์—์„œ text๋ฅผ ์งง๊ฒŒ ํ˜น์€ ๊ธธ๊ฒŒ ๋ˆ„๋ฅผ ๋•Œ ๋œจ๋Š” ๋ฉ”๋‰ด๋ฅผ ์˜๋ฏธํ•œ๋‹ค. shake-motion์€ ํ”๋“ค๋•Œ ๋ฐœ์ƒํ•˜๋Š”๋ฐ, ์ด๊ฒƒ์€ responder chain์—์„œ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๊ณ  core motion ๊ฐ์ฒด๋กœ ์ „๋‹ฌ๋œ๋‹ค.)

 

๐Ÿ”น ์–ด๋–ค Responder๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š”์ง€ ๊ฒฐ์ •ํ•˜๊ธฐ

UIKit์€ ๋ทฐ ๊ธฐ๋ฐ˜์˜ hit-testing์„ ์‚ฌ์šฉํ•˜์—ฌ ํ„ฐ์น˜ ์ด๋ฒคํŠธ๊ฐ€ ์–ด๋””์„œ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ๊ฒฐ์ •ํ•œ๋‹ค. ๋” ๊ตฌ์ฒด์ ์œผ๋กœ ๋งํ•˜๋ฉด, UIKit์€ ํ„ฐ์น˜ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ์œ„์น˜์™€ ๋ทฐ ๊ณ„์ธต์˜ ๋ทฐ ์˜ค๋ธŒ์ ํŠธ์˜ bounds์™€ ๋น„๊ตํ•œ๋‹ค.
UIView์˜ hitTest(_:with: ) ๋ฉ”์„œ๋“œ๋Š” view ๊ณ„์ธต์„ ๋Œ์•„๋‹ค๋‹ˆ๋ฉด์„œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ํ„ฐ์น˜ ์ง€์ ์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” view์˜ ๊ณ„์ธต ๊ฐ€์žฅ ์ตœํ•˜๋‹จ subView๋ฅผ ์ฐพ๊ณ , ๊ทธ๊ฒƒ์„ touch์ด๋ฒคํŠธ์˜ first responder๋กœ ์ง€์ •ํ•œ๋‹ค. ๋งŒ์•ฝ ํ„ฐ์น˜ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•œ ์œ„์น˜๊ฐ€ view์˜ bounds ๋ฐ–์— ์žˆ๋‹ค๋ฉด, hitTest(_:with: )์€ ํ•ด๋‹น ๋ทฐ์™€ ์„œ๋ธŒ๋ทฐ๋ฅผ ๋ชจ๋‘ ๋ฌด์‹œํ•œ๋‹ค. (์•„๋ž˜ hitTest ํฌ์ŠคํŒ… ๋งํฌ๋กœ ๋“ค์–ด๊ฐ€์„œ hitTest์— ๋Œ€ํ•ด์„œ ์‚ดํŽด๋ณด๋ฉด ๋” ๋ช…ํ™•ํ•œ ์ดํ•ด๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค!)

๊ฒฐ๊ณผ์ ์œผ๋กœ view์˜ ์†์„ฑ clipsToBounds๊ฐ€ false๋กœ ์„ค์ •๋˜์–ด ์žˆ์„ ๋•Œ, view์˜ bounds๋ฅผ ๋ฒ—์–ด๋‚œ ์„œ๋ธŒ๋ทฐ์—์„œ ํ„ฐ์น˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋”๋ผ๋„ hitTest๋Š” view๋ฅผ ๋ฆฌํ„ดํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

์™€.. ๋ฌด์Šจ๋ง์ธ์ง€ ์ •๋ง ์ดํ•ด๊ฐ€ ๋˜์ง€ ์•Š์ž–์•„? ๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ hit testing์— ๋Œ€ํ•ด์„œ ์‚ดํŽด๋ณด์ž...... ๋„๋Œ€์ฒด ์ด๊ฑด ๋˜ ๋ญ”๊ฐœ๋…์ด์•ผ!

https://zeddios.tistory.com/536

 

iOS ) hitTest

์•ˆ๋…•ํ•˜์„ธ์š” :) Zedd์ž…๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์†Œ์Šค ๋ณด๋ฉด ๊ฐ€์•„๋” hitTest๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ, ๋ญ์ง€?ํ•˜๊ณ  ๊ทธ๋ƒฅ ์ง€๋‚˜์ณค๋˜ ๊ธฐ์–ต์ด... ์˜ค๋Š˜ ์ œ๋Œ€๋กœ ๊ณต๋ถ€ํ•ด๋ณผ๋ ค๊ณ  ํ•ด์šฉ ์ด๋ฅผ ์œ„ํ•ด์„œ..UIResponder๋ฅผ ์ผ์—ˆ์ฃ .. hi

zeddios.tistory.com

 

์ด๋ ‡๊ฒŒ ์˜ค๋Š˜์€ UIResponder์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ดค๋‹ค. ํ•˜๋‚˜์˜ ๊ฐœ๋…์„ ์•Œ๊ธฐ์œ„ํ•ด์„œ ๋ช‡๊ฐœ์˜ ๊ฐœ๋…์„ ์ฐพ์•„๋ดค๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค. ๋”์ด์ƒ ์ƒˆ๋กœ์šด ๊ฐœ๋…์„ ๋จธ๋ฆฌ์— ๋„ฃ์œผ๋ฉด ์•„๋ฌด๊ฒƒ๋„ ๋‚จ์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™๊ธฐ์—, ์˜ค๋Š˜์€ responder์— ๋Œ€ํ•œ ์ •์˜์™€ ๊ฐœ๋…๋งŒ ์ •ํ™•ํ•˜๊ฒŒ ์ดํ•ดํ•œ ๊ฒƒ์œผ๋กœ ๋งŒ์กฑํ•˜๊ณ , hitTest์— ๋Œ€ํ•œ ๊ฐœ๋…์€ ๋‹ค์Œ ํฌ์ŠคํŒ…์œผ๋กœ ๋งŒ๋‚˜๋ณด์ž.... 

 

๐Ÿ‘€ hitTest์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๋Ÿฌ๊ฐ€๊ธฐ ๐Ÿ‘‰

https://didu-story.tistory.com/292

 

[UIKit] hitTest(_: with: ) - ํ„ฐ์น˜์ด๋ฒคํŠธ์— ๋ฐ˜์‘ํ•  view ์ฐพ๊ธฐ, first responder

์ด์ „๊ธ€์—์„œ UIResponder์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€ํ•˜๋‹ค๊ฐ€ hitTest์— ๋Œ€ํ•œ ๊ฐœ๋…์ด ๋“ฑ์žฅํ–ˆ๋‹ค. https://didu-story.tistory.com/286 [UIKit] UIResponder (feat. Responder, Responder Chain, FirstResponder) ์˜ค๋Š˜๋ถ€ํ„ฐ ๋ฏธ๋ผํด..

didu-story.tistory.com

 

๐Ÿ“– References

https://zeddios.tistory.com/538

 

iOS ) UIResponder

์•ˆ๋…•ํ•˜์„ธ์š” :) Zedd์ž…๋‹ˆ๋‹ค. ์˜ค๋Š˜์€ UIResponder๋ฅผ ๊ณต๋ถ€ํ•ด๋ณด๋ ค๊ณ  ํ•ด์š”. UIResponder ๋ฆฌ์Šคํฐ๋” ๊ฐ์ฒด(Responder objects), ์ฆ‰ UIResponder์˜ ์ธ์Šคํ„ด์Šค๋Š” UIKit ์•ฑ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๋ฐฑ๋ณธ(backbone)์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ ํ•ต..

zeddios.tistory.com

https://jeonyeohun.tistory.com/257

 

[iOS] UIResponder: iOS์˜ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ - Responder Chain๊ณผ First Responder

UITextField ์“ฐ๋ฉด์„œ ๋งŽ์ด ๋ณธ๊ฑฐ.. ์ตœ๊ทผ๋ฐ UITextField๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์‚ฌ์šฉ์ž๊ฐ€ ํ‚ค๋ณด๋“œ์˜ ์—”ํ„ฐ(return)์„ ๋ˆŒ๋ €์„ ๋•Œ ํ˜„์žฌ ํ…์ŠคํŠธ ํ•„๋“œ ๋ฐ”๋กœ ๋‹ค์Œ์— ์žˆ๋Š” ํ…์ŠคํŠธ ํ•„๋“œ๋กœ editing์ด ์ „ํ™˜๋˜๋„๋ก ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š” ์ž‘

jeonyeohun.tistory.com

https://seizze.github.io/2019/11/26/iOS%EC%9D%98-Responder%EC%99%80-Responder-Chain-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0.html

 

iOS์˜ Responder์™€ Responder Chain ์ดํ•ดํ•˜๊ธฐ

UIKit๊ณผ ๊ด€๋ จ๋œ ์• ํ”Œ ๋ฌธ์„œ๋ฅผ ๋ณผ ๋•Œ ๋นˆ๋ฒˆํ•˜๊ฒŒ ๋“ฑ์žฅํ•˜๋Š” Reponder Chain์— ๊ด€๋ จํ•œ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์• ํ”Œ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์˜€์œผ๋ฉฐ, ํฌ์ŠคํŠธ์˜ ๋งจ ์•„๋ž˜ References์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

seizze.github.io

https://woozzang.tistory.com/144

 

[iOS] ๋ฆฌ์Šคํฐ๋” ์ฒด์ธ (Responder Chain) ์ด๋ž€? (feat. UIResponder, First Responder, UIEvent)

 ์•ˆ๋…•ํ•˜์„ธ์š”๐Ÿถ ์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” ๋ฆฌ์Šคํฐ๋” ์ฒด์ธ (Responder Chain) ์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ฆฌ์Šคํฐ๋” ์ฒด์ธ์„ ๊ณต๋ถ€ํ•˜๋ฉด ์•ฑ ๋‚ด์—์„œ ์ด๋ฒคํŠธ๊ฐ€ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ์ „๋‹ฌ๋˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด

woozzang.tistory.com

 

๋ฐ˜์‘ํ˜•