참고 페이지
개요
UINavigationController 기본 클래스는 생성하면 더 이상 navigationBar 및 toolbar 등의 각종 구성 요소들에 대한 변경을 허용하지 않는다. 실제로 API 문서를 보면, 이들 프로퍼티가 readonly 로 되어있음을 확인할 수 있다. 왜 그런지에 대한 고민은 일단 마지막에 하도록 하자
따라서 UINavigaionBar 를 교체하려면 어지간히 골치가 아프다. public 함수들이 극히 제한적인 관계로 오버라이딩해서 프로퍼티를 엎어쓰는 것도 제한적이고, 내부 정책이 어떻게 적용되는 지 도통 알 바가 없다 보니, 이렇게 교체한다고 해서 답이 나오는 것도 아니다.
해법은 의외로 간단한데, UINavigationController 를 위한 xib 를 만드는 것이다. 이렇게 하면 손쉽게 navigation bar 를 자신이 만든 것으로 교체할 수 있다. 같은 방식으로 toolbar 도 교체 가능하리라 본다.
UINavigationController 내의 UINavigationBar 를 자신의 클래스로 교체
- 변경할 UINavigationBar 를 작성한다
- 먼저 UINavigationController 를 위해 빈 xib 를 생성한다.
- xib 화면에 UINavigationController 를 하나 드롭하고, navigation bar 를 선택한 다음, 클래스명에 1에서 만든 UINavigationBar 클래스 명을 입력한다.
-
UINavigationController 생성 시, 기본 생성자인 initWithRootViewController 를 사용하지 말고, UINib 를 사용한다.
- UINib *nib = [UINib nibWithNibName:@"xib명칭" bundle:nil];
- UINavigationController *controller = [[nib instantiateWithOwner:self options:nil] objectAtIndex:0];
- UINib 부분은 관련 내용을 참조할 것
-
위와 같이 생성할 경우 RootViewController 가 없으므로 setViewConttollers 를 통해 이를 설정하는 작업을 수행한다.
- [controller setViewControllers:[NSArray arrayWithObject:rootViewController]];
- 이후부터는 통상적인 방식대로 사용하면 된다.
UINavigationBar 개조
일단 교체한 것은 좋은데, 교체만 했다고 끝나는 것은 아니다. 외형을 자신이 원하는 방식으로 수정해야 할 테니까.
이 부분은 현재 작업 중. 해법이 완전히 나타나면 그 때 적어보도록 하겠다.
왜 그렇게 했을까?
이유를 생각한다면 아주 간단한데, navigation controller 의 navigation bar 를 제멋대로 바꿔버릴 경우, UI 레이아웃이 엉망이 될 것은 불보듯 뻔한 일이며, 이에 대한 제어 정책을 수립하는 것 자체가 굉장히 까다로운 일임을 알 수 있다. 뭐 결과적으로는 생성 시점에 설정해두는 것이 최선인 셈.
Reflection 을 지원하는 환경에서라면 이런 부분에 대응하기 위하여, 생성 시점에 내부적으로 사용할 클래스 타입을 그대로 받아 생성하는 방법을 종종 사용하곤 한다. (자바 API 쪽 계통이 이런 게 좀 있다.) 하지만, 코드레벨에서 특정 타입을 그대로 인자로 넘기는 게 Reflection 에 대한 개념이 마땅히 서 있지 않은 경우에는 참 이해하기 어려운 패턴이기도 한데다, 어쨌거나 생성자에 넣어야 하므로 생성자가 복잡해지는 것은 피할 수 없다.
이런 UI 의 복잡한 체계에서 쉽게 생각할 수 있는 좋은 방법은 적절한 규격화를 통해 serialization 된 데이터로부터 개체 전체를 생성하는 것이다. 즉 iOS 라면 nib, xib 가 될 것이다.
사실 이와 같은 패턴을 적용한 다른 환경도 존재한다. Java 하시는 분들이라면 다들 알고 있는 swing 패키지로서, swing 의 lookAndFeel 패키지는 이런 접근방식으로만 처리되어, 특정 lookAndFeel 에 대하여 일부만 상속받아 수정한다거나 하는 것은 안되고, 미리 설정된 클래스에 대해서 생성 시점에 알아서 로드하는 구조로 되어 있다. 생성 시점에 필요한 클래스를 커스텀하는 방법은 이런 해법이 가장 번거로움을 줄일 수 있는 것이라 본다.
이 글은 스프링노트에서 작성되었습니다.