- ๊ณต์๋ฌธ์-Using Responders and the Responder Chain to Handle Events
- ๊ณต์๋ฌธ์-Responder Object ๋ ์์๋ณด๊ธฐ(UIResponder)
- iOS์ Responder์ Responder Chain ์ดํดํ๊ธฐ
@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 ํ๋กํผํฐ์ ํ ๋นํ์ธ์.
UIKit Responder
๋ค์ ์ด๋ฒคํธ ์ฒ๋ฆฌ ์์
์ธ์, ์ฒ๋ฆฌ ๋์ง ์์ ์ด๋ฒคํธ๋ฅผ ๋ค๋ฅธ ๊ฐ์ฒด๋ก forwardingํ๋ ์ญํ ๋ ์ํํฉ๋๋ค.
Responder Chain
์ responder ๊ฐ์ฒด๋ค์ด ์ด๋ฒคํธ๋ ์ก์
๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ ์ฑ
์์ ์ฑ ๋ด์ ๋ค๋ฅธ ๊ฐ์ฒด๋ค์๊ฒ ์ ์กํ ์ ์๋๋ก ํด์ค๋๋ค. ์ด๋ฅผ ํตํด ์ ํด์ง responder๊ฐ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ์ง ์์ ๊ฒฝ์ฐ, ํด๋น responder๋ ๊ทธ ์ด๋ฒคํธ๋ฅผ responder chain์ ์กด์ฌํ๋ ๋ค์ ๊ฐ์ฒด์๊ฒ forwardingํ๊ฒ ๋ฉ๋๋ค. ์ด์ ๊ฐ์ ๊ณผ์ ์ด ๊ณ์ ๋ฐ๋ณต๋๋ฉฐ ๋ง์ง๋ง๊น์ง ์ฒ๋ฆฌ๋์ง ์์ ๊ฒฝ์ฐ, ์ฑ์ด ํด๋น ๋ฉ์์ง๋ฅผ ๋ฒ๋ฆฝ๋๋ค.
์ผ๋ฐ์ ์ธ ์ด๋ฒคํธ๋ responder chain ๋ด์ first responder ํน์ ํฐ์น๋ ๋ทฐ์์ ์์ํ์ฌ ๋ทฐ ๊ณ์ธต์ ๋ฐ๋ผ window ๊ฐ์ฒด๋ฅผ ๊ฑฐ์ณ app ๊ฐ์ฒด์ ๋๋ฌํ ๋๊น์ง ์ด๋ํฉ๋๋ค. UIKit์ ์ผ์ ํ ๊ท์น์ ์ฌ์ฉํ์ฌ responder chain์ ๋์ ์ผ๋ก ๊ด๋ฆฌํ๋๋ฐ, ์ด ๊ท์น์ ์ํด ์ด๋ค ๊ฐ์ฒด๊ฐ ๋ค์ ์์๋ก ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ง๊ฐ ๊ฒฐ์ ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ทฐ๋ ์์ ์ ์ํผ๋ทฐ์๊ฒ๋ ์ด๋ฒคํธ๋ฅผ forwardingํ๊ณ , ๋ทฐ ๊ณ์ธต์ ๋ฃจํธ ๋ทฐ๋ ์์ ์ ๋ทฐ ์ปจํธ๋กค๋ฌ์๊ฒ๋ก ์ด๋ฒคํธ๋ฅผ ํฌ์๋ฉํฉ๋๋ค.
Responder chains in an app
- Text field๊ฐ ์ด๋ฒคํธ๋ฅผ ํธ๋ค๋งํ์ง ์์ผ๋ฉด, UIKit์ text field์ ๋ถ๋ชจ์ธ UIView ๊ฐ์ฒด์๊ฒ๋ก ์ด๋ฒคํธ๋ฅผ ๋ณด๋ด๊ณ , ์ด์ด์ ์๋์ฐ์ ๋ฃจํธ ๋ทฐ์๊ฒ๋ก ๋ณด๋ ๋๋ค.
- ๋ฃจํธ ๋ทฐ์์, Responder chain์ ์ด๋ฒคํธ๋ฅผ ์๋์ฐ๋ก ๋ณด๋ด๊ธฐ ์ ์ ๋ฐฉํฅ์ ๋ฐ๊พธ์ด ๋ฃจํธ ๋ทฐ๋ฅผ ์์ ํ๊ณ ์๋ ๋ทฐ ์ปจํธ๋กค๋ฌ์๊ฒ๋ก ๋ณด๋ ๋๋ค.
- ๋ง์ฝ ์๋์ฐ๊ฐ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ์ง ๋ชปํ๋ฉด, UIKit์ ์ด๋ฒคํธ๋ฅผ UIApplication ๊ฐ์ฒด์๊ฒ๋ก ๋ณด๋ ๋๋ค. ๊ทธ๋ฆฌ๊ณ app delegate๊ฐ UIResponder์ ์ธ์คํด์ค์ด๊ณ responder chain์ ์ผ๋ถ๊ฐ ์๋๋ผ๋ฉด ์ด๋ฒคํธ๋ฅผ app delegate์๊ฒ๋ก ๋ณด๋ ๋๋ค.
์์์ ์์๋ดค๋ฏ Responder๋ raw event data๋ฅผ ์์ ํ๊ณ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๊ฑฐ๋ ๋ค๋ฅธ resopnder ๊ฐ์ฒด๋ก ์ ๋ฌํ๋ ์ญํ ๋ ํด์ผํฉ๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ฑ์ด ์ด๋ฒคํธ๋ฅผ ์์ ํ๋ฉด UIKit์ ์๋์ ์ผ๋ก ๊ฐ์ฅ ์ ์ ํ responder ๊ฐ์ฒด์๊ฒ ์ฐ๊ฒฐํด์ค๋๋ค. ์ด ๋, ๊ฐ์ฅ ์ ์ ํ responder๊ฐ์ฒด๋ฅผ first responder
๋ผ๊ณ ์นญํฉ๋๋ค.
์ด๋ฒคํธ๋ฅผ ๋ฐ๊ธฐ ์ํด์ responder๋ ์์ ์ด first responder
๊ฐ ๋ ์ ์์์ ๋ํ๋ด์ผ ํฉ๋๋ค. ๊ทธ๋ฌ๊ธฐ ์ํด์ ์ฐ๋ฆฌ๋ UIResponder์ ์๋ธํด๋์ค์์ canBecomeFirstResponder
ํ๋กํผํฐ๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ์ฌ true๋ฅผ ๋ฆฌํดํ๋๋ก ๋ง๋ค์ด์ผ ํฉ๋๋ค.
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์ ๋ฐ๋ผ ์ด๋ํฉ๋๋ค.
UIKit์ ์ด๋์ ํฐ์น ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋์ง๋ฅผ ๊ฒฐ์ ํ๊ธฐ ์ํด ๋ทฐ ๊ธฐ๋ฐ hit-testing์ ์ฌ์ฉํฉ๋๋ค. UIKit์ ํฐ์น ์์น๋ฅผ ๋ทฐ ๊ณ์ธต์ ์๋ ๋ทฐ ๊ฐ์ฒด์ ๋ฐ์ด๋์ ๋น๊ตํฉ๋๋ค. UIView์ hitTest(_:with:) ๋ฉ์๋๋ ํน์ ํฐ์น๋ฅผ ํฌํจํ๋ ๊ฐ์ฅ ๊น์ ์๋ธ๋ทฐ๋ฅผ ์ฐพ๊ธฐ ์ํด ๋ทฐ ๊ณ์ธต์ ๋ฐ๋ผ์ ์ด๋ํ๊ณ , ์ด ๊ฐ์ฅ ๊น์ ์๋ธ๋ทฐ๊ฐ ํฐ์น ์ด๋ฒคํธ์ first responder๊ฐ ๋ฉ๋๋ค.
ํฐ์น ์์น๊ฐ ๋ทฐ์ ๊ฒฝ๊ณ ๋ฐ์ด๋ผ๋ฉด, hitTest(_:with:) ๋ฉ์๋๋ ํด๋น ๋ทฐ์ ๊ทธ ๋ทฐ์ ๋ชจ๋ ์๋ธ๋ทฐ๋ค์ ๋ฌด์ํฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก, ๋ทฐ์ clipToBounds ํ๋กํผํฐ๊ฐ false๋ผ๋ฉด, ๊ทธ ๋ทฐ์ ๋ฐ์ ์๋ ์๋ธ๋ทฐ๋ค์ ํฐ์น๋ฅผ ํฌํจํ๋๋ผ๋ ๋ฐํ๋์ง ์์ต๋๋ค.
ํฐ์น๊ฐ ์ผ์ด๋๋ฉด, UIKit์ UITouch ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ ๋ทฐ์ ์ฐ๊ฒฐํฉ๋๋ค. ํฐ์น ์์น๋ ๋ค๋ฅธ ํ๋ผ๋ฏธํฐ๋ค์ด ๋ณ๊ฒฝ๋๋ฉด, UIKit์ ๊ฐ์ UITouch ๊ฐ์ฒด๋ฅผ ์๋ก์ด ์ ๋ณด๋ก ์ ๋ฐ์ดํธํฉ๋๋ค. ๋ณ๊ฒฝ๋์ง ์๋ ์ ์ผํ ํ๋กํผํฐ๋ ๋ทฐ์ ๋๋ค. ์ฌ์ง์ด ํฐ์น ์์น๊ฐ ์๋ ๋ทฐ์ ๋ฐ๊นฅ์ผ๋ก ์ด๋ํ๋๋ผ๋, ํฐ์น์ view ํ๋กํผํฐ์ ๊ฐ์ ๋ณํ์ง ์์ต๋๋ค. ํฐ์น๊ฐ ๋๋๋ฉด, UIKit์ UITouch ๊ฐ์ฒด๋ฅผ ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ํฉ๋๋ค.