2014년 12월 15일 월요일

NSView 배경색과 모서리에 관한 트릭(?)

UIView와 NSView는 다르다는 것을 또다시 체험해 보는 시간(-_-). 편의상 이젠 Objective-C 코드 예제는 생략하고 Swift 코드 예제만 남긴다. 어차피 메소드나 프로퍼티 명은 거의 동일하니...

[참고] 이 글은 NSView Cheatsheet 글에 요약해서 정리되어 있다.

1. NSView의 배경색

NSView는 backgroundColor 같은 프로퍼티가 존재하지 않는다. 그렇다면 NSView는 항상 투명한(clearColor) 존재인 것일까. 뭐 이런 건 일단 넘어가고...

결국 배경색 프로퍼티가 없으므로 NSView를 서브클래싱 해서 drawRect 메소드를 오버라이드 해서 색을 그려야 된다는 이야기가 된다.
class SomeCustomView: NSView {
    ...

    override func drawRect(dirtyRect: NSRect) {
        NSColor.blackColor().setFill()
        NSRectFill(dirtyRect)

        super.drawRect(dirtyRect)
    }

    ...
}
위 예제는 까만색으로 배경을 칠하는 예제 코드이다. 안타깝지만 이 방법이 최선인 것 같다.

당연하겠지만, 원하는 색이 있다면 NSColor로 색을 만들고 이 색(NSColor 오브젝트)에서 setFill() 메소드를 호출해서 선택해 주면 된다.

만약 NSWindow를 특수하게 이용(?)하지 않고 윈도우 전체의 배경색을 바꾼다면 차라리 NSWindow의 backgroundColor 를 변경하는 것이 더 편하다.

2. NSView의 모서리를 둥글게 하기

UIView(혹은 서브클래스)의 경우 layer의 cornerRadius 값과 masksToBounds 값을 세팅함으로써 모서리를 둥글게 만들 수 있었다. NSView도 동일한 프로퍼티가 존재한다. 그럼 쉽게 되겠네?

하지만 NSView의 경우는 layer에 그냥(?) 접근하는 것 자체가 안된다. 아마도 Swift로 코딩해보면 Optional Nil 에 접근하게 되어서 앱이 죽어버릴 것이다.

해답은 NSView의 wantsLayer 플래그이다. 이 플래그를 true로 세팅하면 layer 참조가 가능해진다. 그런데 불행히도 이 변수는 NSView가 아닌 외부에서의 접근이 막혀있는 것 같다.

해결방법은 역시 NSView를 서브클래싱 하는 것이다.
class SomeCustomView: NSView {
    // Programmatic Initializer
    override init(frame: NSRect) {
        self.wantsLayer = true
        self.layer!.cornerRadius = 10
        self.layer!.masksToBounds = true
    }

    // If the view was created by XIB
    override func awakeFromNib() {
        self.wantsLayer = true
        self.layer!.cornerRadius = 10
        self.layer!.masksToBounds = true
    }

    ...
}
위 예제는 두 가지 메소드를 오버라이드 하고 있는데 상황에 따라 둘 중 하나만 있으면 된다. init의 경우 코드로 이 뷰를 생성할 때 호출되고 awakeFromNib는 인터페이스 빌더로 특정 뷰의 클래스를 이 클래스로 했을 경우 호출된다.

물론 둘 다 만들어 두고 동일한 코드를 다른 메소드로 모듈화 하는 엘레강스한 방법이 좋을 것이다.

댓글 없음 :