ASH84

Software Engineer/Developer, co-founder of Payhere. Ex-Banksalad. Intereseted in iteroperability, bootstrap company, writting.

[Cocoa Design Pattern]18ch. Responder Chain

created:2011-06-17
updated:2015-07-03
edit

코코아 디자인 패턴 18장. 리소폰더 체인

**








2011/06/11 – [Technique/iOS Dev] – [Cocoa Design Pattern] 17ch. Outlet, Target, Action


**


리스폰더 체인이란? 



 
– 코코아 그래픽 애플리케이션의 핵심적이고 중요한 요소

 – 책임사슬 패턴(Chain of Responsibility)


*

패턴이 만들어진 동기 




 
– 사용자 이벤트의 정확한 전달

– 현재 활성화 되어 있는 인터페이스 객체는 무엇이고, 어떻게 액션 메시지를 전달할 것인가. 




패턴으로 문제 해결




– 
책임사슬패턴은 메시지의 전송자와 수신자 객체 관계를 최대한 분리시키는 것이 목적 

– 수신객체들이 연결 리스트로 구성되어 있고, 각 객체들이 메시지를 무시 혹은 수신하는 순차적인 시스템 




용어 




 
NSResponder

 
– 사용자 입력을 다룰수 있는 개체들은 모두 NSResponder의 서브클래스

 – 키보드, 마우스, 터치등의 상자 입력에 대응하는 역할


 – NSWindow, NSView, NSViewController, NSDrawer 등이 모두 NSResponder의 서브 클래스




 * 사용자의 초점이 어디에 맞춰져 있는지 자동적으로 코코아 프레임워크에서 기억.




 
KeyWindow

 
– 입력을 받는 윈도우를 키 윈도우

*

Main Window


 
– 현재 초점이 맞춰져 있는 문서 창을 메인 윈도우



* 키윈도우와 메인 윈도우가 하나의 인터페이스 인 경우도 있지만, 서로 다른 인터페이스인 경우 있음.




NSApplication 의 역할 




 
– 애플리케이션 객체는 키 윈도우와 메인 윈도우를 항상 기억하도록 되어 있음.

 – keyWindow, mainWindow 를 통해서 해당 개개체에 대한 레퍼런스를 얻을수 있음. 




FirstResponder


 
– 현재 초점이 맞춰져 있는 뷰를 지칭함

 – 리스폰더 체인의 첫번째 객체


 – -firstResponder : 첫번째 리스폰더에 대한 레퍼런스 
리스폰더 체인

 
– 다수의 수신 객체가 엮여져 있는 형태로 액션 메시지의 대해서 각 노드가 ignore 또는 accept 를 하는 구조

 – nextResponder : 주어진 수신객체의 다음 수신객체를 반환


 – setNextResponder : 다음 객체를 재설정하고 싶을때 사용




 – 일반적으로 주어진 뷰의 다음 수신객체는 슈퍼뷰(super view)


 – 윈도우 내 콘텐츠 뷰의 다음 수신객체는 윈도우. 


 – 윈도우의 다음 수신 객체는 nil. 


 – 리스폰더 체인의 마지막 노드가 윈도우 창이다. 




 예외) NSWindowContorller에 의해서 제어되고 있는 윈도우 창은 컨트롤러가 최종 수신 객체임 


 예제) 304p


 


 – 모든 리스폰더 체인은 nil로 끊어지기 때문에, 무한 루프의 위험성이 없다.


 – 윈도우가 여러개인 환경에서는 모든 각각의 윈도우가 리스폰더 체인을 가짐.


 – 윈도우 내 사용자의 선택이 바뀔때 마다 리스폰더체인이 업데이트 됨.




 – acceptResponder : 새로운 수신객체가 될 객체에게 전달


 – resignFirstResponder : 현재 리스폰더에게 FirstResponder를 반환하라는 메시지를 전달


– becomeFirstResponder : 새로운 첫번째 리스폰더가 될 객체에게 전달 – 키보드가 마우스 입력의 경우,




NSApplcation 객체가 입력을 NSEvent 객체로 변환한 다음. 리스폰더 객체를 찾는다.


 – 리스폰더 체인은 계층구조를 이용해서 FirstResponder를 찾아냄. 






확장된 리스폰더 체인




 
– 키 윈도우와 메인 윈도우의 리스폰더 체인을 아우르고, 또한 공용의 NSApplication 인스턴스와

   NSDocumentController 인스턴스를 포함한 확장 리스폰더 체인.




 – nil을 target을 갖는 메시지를 담당.


 – 메뉴 항목의 경우 다양한 종류의 메시지 구현이 쉽지 않다.


 – 키 윈도우와 메인 윈도우의 리스폰더 체인 만으로는 이벤트 핸들링이 불충분한 경우.


 – 확장된 리스폰더 체인의 순서




 1. 키 윈도우의 리스폰더 체인의 첫번째 리스폰더를 처음 시도. 


 2. 뷰 계층 구조의 리스폰더 체인을 따라 메시지 전달.


 3. 윈도우 객체를 시도


 4. 윈도우의 델리게이트를 시도(주로 NSDocument의 인스턴스)


 5. 만약, NSWindowController가 있다면 시도.  


 6. 1-5의 순서를 메인 윈도우에 적용 


 7. NSApplication 객체와 그의 델리게이트를 시도


 8. NSDocumentController 가 있다면 시도. 




예제) 306P – 307P




– 키 윈도우 == 메인윈도우의 경우, 확장된 리스폰더 체임의 검색 길이는 짧아 짐. 


– 인터페이스 빌더 이용시, 컨트롤을 첫번째 리스폰더에 연결하면, 실제로는 해당 액션에 대한 target를 nil로 지정.


– 어떤 컨트롤의 액션메시지를 확장된 리스폰더 체인에 전달하고 싶다면 action의 target을 nil로 지정하면 됨. 




[mycontrol setAction:@selector(terminate)];


[mycontrol setTarget : nil];




NSApplication의 -sendAction:to:from: 메소드에서 확장된 리스폰더 체인으로 보내는 방법 




   [NSApp sendAction:@selector(terminate) to:nil from:self];




메시지를 보내지 않으면서 어떤 객체가 대응하도록 되어 있는지 알고 싶다면, 




     id myTarget = [NSApp  targetAction:@selector(terminate) to:nil from:self];




확장된 리스폰더 체인 탐색하기


 
 – 리스폰더 체인의 정보를 출력해서 볼수가 있음 : 308p 예제 





리스폰더 체인에 객체 삽입하기 




 
– 수동으로 객체 삽입 가능 : NSResponder 의 서브클래스면 가능함.

 – 뷰와 뷰의 superView 사이에 뷰 컨트롤러를 삽입해야 하는 경우




 NSResponder * theNextResponder  = [myview nextResponder];


[myview setNextResponder : myViewController];


[myviewController setNextResponder:theNextResponder];




 – 뷰 컨트롤러가 뷰 다음에 위치하게 되면, 그 뷰가 활성화될 경우에만 작동하게 됨. 


  (주어진 윈도우가 하나 이상의 뷰/뷰 컨트롤러 짝을 가지고 있는 경우를 위해서임)


 


 – 리스폰더 체임의 어느위치에 객체를 삽입하느냐에 따라 컨트롤러가 언제 어느 식으로 사용자 입력에 대응하도록 할 것인지를 조정 할 수 있음






 
*리스폰더 체인 활용하기 



 
– 이미 존재하고 있는 리스폰더 체인을 사용하는 것이 가장 편함. 

– 자동검열 기능, 텍스트의 선택여부에 따른 액션 지정 등은 컨텍스트에 민감한 행동 기능을 리스폰더 체인을 통해서 단순화 시킬수가 있다.


*

코코아 사용예제 




 
**코코아에서 리스폰더 체인은 핵심임. 

 – 사용자 입력은 NSApplication 객체가 책임을 지고 적합한 리스폰더 체인에게 전달됨.


 – 키 윈도우와 메인 윈도우의 리스폰더 체인을 아우르고, 또한 공용의 NSApplication 인스턴스와


    NSDocumentController 인스턴스를 포함한 확장 리스폰더 체인.




 – nil을 target을 갖는 메시지를 담당.


 – 애플리케이션의 상태에 따라 목표물이 동적으로 좌우되는 액션을 구현해야 한다면, target을 nil로 지정.


 – 복사하기/붙여넣기, 눈금자 조절기능, undo/redo 등의 기능이 확장 리스폰더 체인의 대상


 – 컨텍스트 인식 메뉴들도 리스폰더 체인을 많이 활용  






 
패턴 사용 결과



 – 다양한 사용자 입력을 처리 할수 있는 유연성을 제공함.


 – 다양한 액션 기능을 최소한의 코드로 구현 가능함.


 – 리스폰더 체인을 활용해서 애플리케이션에 특화된 컨텍스트 인식기능의 구현 가능.  


#cocoa design pattern  #dev  #iPhone dev  #ResponderChain  #리스폰더 체인  #코코아 디자인 패턴