Skip to content

Latest commit

ย 

History

History
90 lines (58 loc) ยท 8.33 KB

Responder-Chain.md

File metadata and controls

90 lines (58 loc) ยท 8.33 KB

Responder Chain ๊ตฌ์กฐ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜๊ณ , First Responder ์—ญํ• ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜์‹œ์˜ค.

์ฐธ๊ณ ํ•œ ์ข‹์€ ๊ธ€

ํ•จ๊ป˜๋ณด๋ฉด ์ข‹์€ ๋‹ต๋ณ€

๋‹ต๋ณ€

UIResponder

@available(iOS 2.0, *)
open class UIResponder : NSObject, UIResponderStandardEditActions {

    open var next: UIResponder? { get }
    
    open var canBecomeFirstResponder: Bool { get } // default is NO
    open func becomeFirstResponder() -> Bool

    open var canResignFirstResponder: Bool { get } // default is YES
    open func resignFirstResponder() -> Bool

    open var isFirstResponder: Bool { get }
    // ...
}

Responder ๊ฐ์ฒด๋Š” ์ด๋ฒคํŠธ๋ฅผ ํ•ธ๋“ค๋งํ•˜๊ณ  ์ด๋ฒคํŠธ์— ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ๋Š” UIReponder์˜ ์ธ์Šคํ„ด์Šค์ž…๋‹ˆ๋‹ค. UIApplication, UIViewController ๊ฐ์ฒด๋“ค, ๋ชจ๋“  UIView ๊ฐ์ฒด๋“ค(UIWindow ๊ฐ์ฒด ํฌํ•จ)์„ ํฌํ•จํ•œ ๋งŽ์€ ์ฃผ์š” ๊ฐ์ฒด๋“ค ๋˜ํ•œ reponder์ž…๋‹ˆ๋‹ค. ์ด๋ฒคํŠธ๊ฐ€ ์ผ์–ด๋‚˜๋ฉด, UIKit์€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋ง์„ ์œ„ํ•ด ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ ์•ฑ์˜ reponder ๊ฐ์ฒด๋“ค์—๊ฒŒ ๋ณด๋‚ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ์˜ ์ข…๋ฅ˜์—” touch events, motion events, remote-control(์›๊ฒฉ์กฐ์ข…) events, ๊ทธ๋ฆฌ๊ณ  press events ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํŠน์ • ์ด๋ฒคํŠธ๋“ค์„ ํ•ธ๋“ค๋งํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” responder๊ฐ€ ํ•ด๋‹น ์ด๋ฒคํŠธ์— ๋Œ€์‘๋˜๋Š” ๋ฉ”์„œ๋“œ๋“ค์„ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ„ฐ์น˜ ์ด๋ฒคํŠธ๋ฅผ ํ•ธ๋“ค๋งํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” responder๊ฐ€ touchesBegan(_:with:), touchesMoved(_:with:), touchesEnded(_:with:), touchesCancelled(_:with:) ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ„ฐ์น˜์˜ ๊ฒฝ์šฐ์—, responder๋Š” ํ„ฐ์น˜์˜ ๋ณ€ํ™”๋ฅผ ํŠธ๋ž˜ํ‚นํ•˜๊ณ  ์•ฑ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ ์ ˆํžˆ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ์œ„ํ•ด์„œ UIKit์—์„œ ์ œ๊ณตํ•˜๋Š” ์ด๋ฒคํŠธ ์ •๋ณด๋ฅผ ์ด์šฉํ•ฉ๋‹ˆ๋‹ค.

Responder๋“ค์€ UIEvent๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ input view๋ฅผ ํ†ตํ•ด ์ปค์Šคํ…€๋œ input์„ ๋ฐ›์•„๋“ค์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. system keyboard๊ฐ€ ํ›„์ž์˜ ๊ฒฝ์šฐ๋ฅผ ๊ฐ€์žฅ ์ž˜ ๋‚˜ํƒ€๋‚ด๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์œ ์ €๊ฐ€ UITextField๋‚˜ UITextView๋ฅผ ํƒญํ•˜๋ฉด view๋Š” first responder๊ฐ€ ๋˜๊ณ  input view๋ฅผ ๋„์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ input view๋Š” system keyboard์ด์ฃ .
์ด์™€ ๋น„์Šทํ•˜๊ฒŒ ์šฐ๋ฆฌ๋„ ์ปค์Šคํ…€ input view๋ฅผ ๋งŒ๋“ค๊ณ  ๋‹ค๋ฅธ responder๊ฐ€ ํ™œ์„ฑํ™” ๋  ๋•Œ ์ปค์Šคํ…€๋œ input view๋ฅผ ๋„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปค์Šคํ…€ input view๋ฅผ responder์— ์—ฐ๊ฒฐํ•˜๋ ค๋ฉด, ํ•ด๋‹น ๋ทฐ๋ฅผ responder์˜ inputView ํ”„๋กœํผํ‹ฐ์— ํ• ๋‹นํ•˜์„ธ์š”.


Responder Chain

UIKit Responder๋“ค์€ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ์ž‘์—… ์™ธ์—, ์ฒ˜๋ฆฌ ๋˜์ง€ ์•Š์€ ์ด๋ฒคํŠธ๋ฅผ ๋‹ค๋ฅธ ๊ฐ์ฒด๋กœ forwardingํ•˜๋Š” ์—ญํ• ๋„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
Responder Chain์€ responder ๊ฐ์ฒด๋“ค์ด ์ด๋ฒคํŠธ๋‚˜ ์•ก์…˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•  ์ฑ…์ž„์„ ์•ฑ ๋‚ด์˜ ๋‹ค๋ฅธ ๊ฐ์ฒด๋“ค์—๊ฒŒ ์ „์†กํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ •ํ•ด์ง„ responder๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ, ํ•ด๋‹น responder๋Š” ๊ทธ ์ด๋ฒคํŠธ๋ฅผ responder chain์— ์กด์žฌํ•˜๋Š” ๋‹ค์Œ ๊ฐ์ฒด์—๊ฒŒ forwardingํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด์™€ ๊ฐ™์€ ๊ณผ์ •์ด ๊ณ„์† ๋ฐ˜๋ณต๋˜๋ฉฐ ๋งˆ์ง€๋ง‰๊นŒ์ง€ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์„ ๊ฒฝ์šฐ, ์•ฑ์ด ํ•ด๋‹น ๋ฉ”์‹œ์ง€๋ฅผ ๋ฒ„๋ฆฝ๋‹ˆ๋‹ค.

Responder Chain๋‚ด์—์„œ event๊ฐ€ ์ „๋‹ฌ๋˜๋Š” ๊ฒฝ๋กœ

์ผ๋ฐ˜์ ์ธ ์ด๋ฒคํŠธ๋Š” responder chain ๋‚ด์˜ first responder ํ˜น์€ ํ„ฐ์น˜๋œ ๋ทฐ์—์„œ ์‹œ์ž‘ํ•˜์—ฌ ๋ทฐ ๊ณ„์ธต์„ ๋”ฐ๋ผ window ๊ฐ์ฒด๋ฅผ ๊ฑฐ์ณ app ๊ฐ์ฒด์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. UIKit์€ ์ผ์ •ํ•œ ๊ทœ์น™์„ ์‚ฌ์šฉํ•˜์—ฌ responder chain์„ ๋™์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š”๋ฐ, ์ด ๊ทœ์น™์— ์˜ํ•ด ์–ด๋–ค ๊ฐ์ฒด๊ฐ€ ๋‹ค์Œ ์ˆœ์„œ๋กœ ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์„์ง€๊ฐ€ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ทฐ๋Š” ์ž์‹ ์˜ ์Šˆํผ๋ทฐ์—๊ฒŒ๋„ ์ด๋ฒคํŠธ๋ฅผ forwardingํ•˜๊ณ , ๋ทฐ ๊ณ„์ธต์˜ ๋ฃจํŠธ ๋ทฐ๋Š” ์ž์‹ ์˜ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์—๊ฒŒ๋กœ ์ด๋ฒคํŠธ๋ฅผ ํฌ์›Œ๋”ฉํ•ฉ๋‹ˆ๋‹ค.

Responder chains in an app

  1. Text field๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ํ•ธ๋“ค๋งํ•˜์ง€ ์•Š์œผ๋ฉด, UIKit์€ text field์˜ ๋ถ€๋ชจ์ธ UIView ๊ฐ์ฒด์—๊ฒŒ๋กœ ์ด๋ฒคํŠธ๋ฅผ ๋ณด๋‚ด๊ณ , ์ด์–ด์„œ ์œˆ๋„์šฐ์˜ ๋ฃจํŠธ ๋ทฐ์—๊ฒŒ๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  2. ๋ฃจํŠธ ๋ทฐ์—์„œ, Responder chain์€ ์ด๋ฒคํŠธ๋ฅผ ์œˆ๋„์šฐ๋กœ ๋ณด๋‚ด๊ธฐ ์ „์— ๋ฐฉํ–ฅ์„ ๋ฐ”๊พธ์–ด ๋ฃจํŠธ ๋ทฐ๋ฅผ ์†Œ์œ ํ•˜๊ณ  ์žˆ๋Š” ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์—๊ฒŒ๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  3. ๋งŒ์•ฝ ์œˆ๋„์šฐ๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•˜๋ฉด, UIKit์€ ์ด๋ฒคํŠธ๋ฅผ UIApplication ๊ฐ์ฒด์—๊ฒŒ๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  app delegate๊ฐ€ UIResponder์˜ ์ธ์Šคํ„ด์Šค์ด๊ณ  responder chain์˜ ์ผ๋ถ€๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์ด๋ฒคํŠธ๋ฅผ app delegate์—๊ฒŒ๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

First Responder

์œ„์—์„œ ์•Œ์•„๋ดค๋“ฏ Responder๋Š” raw event data๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ resopnder ๊ฐ์ฒด๋กœ ์ „๋‹ฌํ•˜๋Š” ์—ญํ• ๋„ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์•ฑ์ด ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜๋ฉด UIKit์€ ์ž๋™์ ์œผ๋กœ ๊ฐ€์žฅ ์ ์ ˆํ•œ responder ๊ฐ์ฒด์—๊ฒŒ ์—ฐ๊ฒฐํ•ด์ค๋‹ˆ๋‹ค. ์ด ๋•Œ, ๊ฐ€์žฅ ์ ์ ˆํ•œ responder๊ฐ์ฒด๋ฅผ first responder๋ผ๊ณ  ์นญํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ๋ฅผ ๋ฐ›๊ธฐ ์œ„ํ•ด์„œ responder๋Š” ์ž์‹ ์ด first responder๊ฐ€ ๋  ์ˆ˜ ์žˆ์Œ์„ ๋‚˜ํƒ€๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด์„œ ์šฐ๋ฆฌ๋Š” UIResponder์˜ ์„œ๋ธŒํด๋ž˜์Šค์—์„œ canBecomeFirstResponderํ”„๋กœํผํ‹ฐ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ true๋ฅผ ๋ฆฌํ„ดํ•˜๋„๋ก ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Determining an Eventโ€™s First Responder

UIKit์€ ๋ฐ›์€ ์ด๋ฒคํŠธ์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ์„œ ํŠน์ • ๊ฐ์ฒด๋ฅผ ํ•ด๋‹น ์ด๋ฒคํŠธ์˜ first responder๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

Event type First Responder
Touch events ํ„ฐ์น˜๊ฐ€ ์ผ์–ด๋‚œ ๋ทฐ
Press events ํฌ์ปค์Šค๋ฅผ ๊ฐ€์ง„ ๋ทฐ
Shake-motion events UIKit์ด ์ง€์ •ํ•œ ๊ฐ์ฒด ๋˜๋Š” ์ง์ ‘ ์ง€์ •
Remote-control events UIKit์ด ์ง€์ •ํ•œ ๊ฐ์ฒด ๋˜๋Š” ์ง์ ‘ ์ง€์ •
Editing menu messages UIKit์ด ์ง€์ •ํ•œ ๊ฐ์ฒด ๋˜๋Š” ์ง์ ‘ ์ง€์ •

Control์€ ๊ทธ๋“ค๊ณผ ๊ด€๋ จ๋œ ํƒ€๊ฒŸ ๊ฐ์ฒด์™€ ์•ก์…˜ ๋ฉ”์‹œ์ง€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง์ ‘ ์†Œํ†ตํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ control๊ณผ์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ํ•  ๋•Œ, control์€ ์•ก์…˜ ๋ฉ”์‹œ์ง€๋ฅผ ํƒ€๊ฒŸ ๊ฐ์ฒด๋กœ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. ์•ก์…˜ ๋ฉ”์‹œ์ง€๋Š” event๋Š” ์•„๋‹ˆ์ง€๋งŒ ์—ฌ์ „ํžˆ responder chain์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ control์˜ ํƒ€๊ฒŸ ๊ฐ์ฒด๊ฐ€ nil์ผ ๊ฒฝ์šฐ, UIKit์€ first responder์—์„œ ์‹œ์ž‘ํ•˜์—ฌ ์ ์ ˆํ•œ ์•ก์…˜ ๋ฉ”์‹œ์ง€๋ฅผ ๊ตฌํ˜„ํ•œ ๊ฐ์ฒด๋ฅผ ๋งŒ๋‚  ๋•Œ๊นŒ์ง€ responder chain์„ ๋”ฐ๋ผ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

Determining Which Responder Contained a Touch Event

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

ํ„ฐ์น˜ ์œ„์น˜๊ฐ€ ๋ทฐ์˜ ๊ฒฝ๊ณ„ ๋ฐ–์ด๋ผ๋ฉด, hitTest(_:with:) ๋ฉ”์„œ๋“œ๋Š” ํ•ด๋‹น ๋ทฐ์™€ ๊ทธ ๋ทฐ์˜ ๋ชจ๋“  ์„œ๋ธŒ๋ทฐ๋“ค์„ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ, ๋ทฐ์˜ clipToBounds ํ”„๋กœํผํ‹ฐ๊ฐ€ false๋ผ๋ฉด, ๊ทธ ๋ทฐ์˜ ๋ฐ–์— ์žˆ๋Š” ์„œ๋ธŒ๋ทฐ๋“ค์€ ํ„ฐ์น˜๋ฅผ ํฌํ•จํ•˜๋”๋ผ๋„ ๋ฐ˜ํ™˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ„ฐ์น˜๊ฐ€ ์ผ์–ด๋‚˜๋ฉด, UIKit์€ UITouch ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ๋ทฐ์™€ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ํ„ฐ์น˜ ์œ„์น˜๋‚˜ ๋‹ค๋ฅธ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์ด ๋ณ€๊ฒฝ๋˜๋ฉด, UIKit์€ ๊ฐ™์€ UITouch ๊ฐ์ฒด๋ฅผ ์ƒˆ๋กœ์šด ์ •๋ณด๋กœ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ์œ ์ผํ•œ ํ”„๋กœํผํ‹ฐ๋Š” ๋ทฐ์ž…๋‹ˆ๋‹ค. ์‹ฌ์ง€์–ด ํ„ฐ์น˜ ์œ„์น˜๊ฐ€ ์›๋ž˜ ๋ทฐ์˜ ๋ฐ”๊นฅ์œผ๋กœ ์ด๋™ํ–ˆ๋”๋ผ๋„, ํ„ฐ์น˜์˜ view ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์€ ๋ณ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ„ฐ์น˜๊ฐ€ ๋๋‚˜๋ฉด, UIKit์€ UITouch ๊ฐ์ฒด๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.