코딩하는 나귀

View Controller Programming Guide를 흩어 보기전에 먼저 Cocoa에서 View 계층구조가 무엇이고 어떻게 처리되는지 Cococa Views Guide의 일부 챕터를 통해 알아보는 것이 좋을 듯합니다.

 

사실 여기서 다루는 부분은 iOS 보다는 Mac OS X에 해당하는 내용이 많으며 설명이 어렵습니다. 그냥 읽으시면서 view hierarchy에 대한 개념 윤각만 그려보시면 좋을 듯합니다. view hierarchy에 대한 설명이 딱히 나오는 곳이 없어서 뒤지기 시작했는데... Cocoa View Guide 문서가 좀 어렵군요... 말인 즉은, Cocoa View Programming에 대한 제 이해가 부족하여 번역에도 오역이 있을 수도 있다는 것입니다.(0,.0) (_  _);; 혹시 이 부분에 대한 명확한 이해가 있으신 분은 노트나 추가 설명을 올려주시면 감사하겠습니다. 

 

 

Working with the View Hierarchy

 

자신들이 가지는 그리기(drawing)와 이벤트 처리(event handling)에 대한 직접적인 책임과 함께, view 들은 다른 view들을 담는 그릇(Container)으로서의 역할도 합니다. 이제 부터 view 계층구조(view hierarchy)와 장점 그리고 어떻게 계층(hierarchy) 내의 view들과 어떻게 작업하는지에 대해 이야기 하겠습니다.

 

 

 

What is a View Hierarchy?

 

사용자 이벤트 처리와 드로윙에 대한 책임에 더하여, view 인스턴스들은 다른 view 인스턴스들을 담는 container로써 역할을 할 수 있습니다. 이러한 view들은 서로연결되어 view 계층구조(hierarchy)를 만듦니다. 상속계층을 나타내는 클래스의 계층구조와는 다르게, view의 계층구조는 다른 view들과 연관해, view들의 layout을 정의합니다. 

 

window 인스턴스는 content view라고 불리는 최상위 view 인스턴스에 대한 참조를 가지고 있습니다. content view는 window 내 가시적인 view 계층구조의 root 역할을 합니다. 하나의 view에 속한 view 인스턴스들을 subview라고 합니다. 하나 이상의 view를 포함하고있는 부모 view는 포함된 view 들의 superview로 참조되어짐니다.(그림 1 참조) 하나의 view가 여러개의 subview들을 가질 수 있는데, 이 경우 여러개의 subview들은 오직 하나의 superview를 가지게 됩니다. view와 자신에 속한 subview를 사용자에게 보여주기 위해, 해당 view는 반드시 window의 view hierarchy에 삽입되어야 합니다.

 

그림 1은 window와 window의 view 계층구조를 보여주는 예 입니다.

 

그림 1

 

이 window의 view hierarchy는 다음과 같은 부분을 가집니다.

  • window는 NSWindow 인스턴스에 의해 표시됩니다. 
  • content view는 window의 view 계층구조의 root 역할을 합니다.
  • content view는 사용자 정의 클래스의 인스턴스인 하나의 subview를 가집니다.
  • 사용자 정의 인스턴스는 다시 두개의 subview를 가지는데 하나의 NSButton 인스턴스와 하나의 NSTextField 인스턴스입니다.
  • 버튼과 텍스트 필드의 superview sms NSBox 객체입니다. 사용자 정의 view container는 실재로 버튼과 텍스트 필드 view를 포함하고 있습니다.

 

 

 

Benefits of a View Hierarchy

 

view들을 계층적으로 관리하는 몇가지 장점은 아래와 같은 어플리케이션의 설계에 있습니다.

  • 복잡한 view 기능은 크고 복잡한 view 클래스를 피해, 간단한 NSView 서브클래스들을 사용함으로써 조립합니다. 예를 들면,  그래픽을 활용한 키패드는 각각의 키에 NSButton subview들을 가진 하나의 NSView 서브클래스로 만들 수 있습니다.
  • 각각의 subview의 좌표시스템은 자신의 superview의 좌표시스템과 연관해 위치하게 됩니다. NSView 인스턴스들은, NSView 인스턴스가 이동되거나 좌표시스템이 변경되면 자신의 모든 subview들이 함께 이동되고 변경되도록, 그들의 superview 내에 위치하게 됩니다. 유사하게, 각각의 view는 자신의 좌표시스템 내에서 그리기를 수행하기 때문에, 그들이 어디에 있던, 그들의 superview가 어디로 옮겨지던, 또는 사이즈가 어떻게 조정되던 상관없도록 자신들의 그리기 명령을 상수로 유지합니다.
  • view hierarchy는 이벤트 처리에 대한 책임을 명확하게 합니다. 응답하지 못하는 이벤트를 수신하면, 처리를 위해 이벤트는 superview까지 view hierarchy를 거슬러 올라가게 됩니다.  key window의 view hierarchy는 어플리케이션의 responder chain에 참여합니다.
  • view hierarchy는 또한 윈도우의 컨텐츠의 다시그리기를 관리하기 위한 정의된 구조를 제공합니다. NSView 인스턴스가 display 요청을 받으면, 인스턴스는 자기자신을 그리는 작업을 수행한 후 차례로 각각의 subview에 display 요청을 보냅니다. view hierarchy 각각의 브린치의 그리기 작업이 완료되면 다음 브린치가 시작하는 식으로 display를 수행하게 됩니다.
  • view hierarchy는 동적입니다. 즉, 어플리케이션 실행시 재 설정될 수 있습니다. view 인스턴스들은 윈도우에서 윈도우 옮겨 질 수 있으며 superview의 subview로 위치할 수도 있습니다.

 

 

 

Locating Views in the View Hierarchy

 

view의 계층 구조에 접근할 수 있는 다양한 함수가 제공됩니다. 

  • [instanceOfNSView subviews] : view의 직계 자손 객체들을 포함하는 배열을 반환. (UIView의 경우 property로 read only)
  • [instanceOfNSView superview] : 메시지 수신자를 포함하고 있는 view를 반환. 메시지 수신자가 view의 root 일경우 superview 에 대한 요청에 nil을 반환. (UIView의 경우 property로 read only)
  • [instanceOfNSView window] : view가 존재하고 있는 window를 반환. view가 윈도우의 view hierarchy에 속하지 않을 경우 nil을 반환. (UIView의 경우 property로 read only)

 

그림2 계층구조에서 객체들의 관계

 

 

아래와 같은 다른 함수들은 view들 간의 관계를 점검하기 위한 함수들입니다. 

  • isDescendantOf: 함수는 수신자가 주어진 view의 subview인지를 묻습니다. subview일경우 YES를, 수신자와 주어진 view가 동일하거나 subview가 아닐경우 NO를 반환합니다. (UIView의 경우 isDescendantOfView: 함수)
  • ancestorSharedWithView: 함수는 인자로 주어진 view 인스턴스와 수신자를 포함하고있는 공통의 container(view hierarchy 상에서 상위계층에 있는 view)를 찾습니다. (NSView only, Mac OS X)

예를 들어, 그림 2와 같은 view hierarchy에서 viewC에 contentView를 인자로하여 isDescendantOf: 함수를 보내면 YES를 반환합니다. viewB에 viewC를 인자로 ancestorSharedWithView: 메시지를 보내면 viewA를 반환합니다.

 

 

 

Adding and Removing Views from a Hierarchy

 

initWithFrame: 함수를 사용하여 view subclass를 생성하면, NSView 객체의 사각프레임 하나가 만들어 집니다. 하지만 이것이 윈도우의 view hierarchy에 포함되어 생성되지는 않습니다. 생성된 view subclass를 윈도우 view hierarchy에 포함시키기 위해서는 addSubview: 메시지를 원하는 superview에 보내야 합니다. 그런 후에야 사각 프레임은 superview의 관점에서 새로운 view에 대한 view hierarchy상의 위치와 superview의 윈도우에서의 위치 모두 알맞게 해석되어 집니다. view hierarchy 상의 기존의 view는 superview에 replaceSubview:with: 메시지(Mac OS X)를 보냄으로써 대치될 수 있습니다. 이밖에 addSubview:positioned:relativeTo: 함수(Mac OS X)로 view의 위치를 정의할 수 있습니다.

 

주의 : 성능 이슈로, Cocoa는 view hierarchy 상에서 하나의 superview 하위의 형제 view들 간의 클리핑(clipping)을 수행하지 않으며 이런 view 들이 오버랩 될때 그리기 동작 수행을 실행 하지 않습니다. 만일 하나의 view가 다른 view의 전면에 그려져야 한다면 여러분 전면의 view를 후면 view의 subview로 만들어야 합니다.

 

removeFromSuperview 메시지를 보내 view hierarchy에서 view를 제거할 수 있습니다. removeFromSuperviewWithoutNeedingDisplay 함수(Mac OS X) 역시 유사하게, 이 메시지를 수신하는 수신자를 수신자의 superview에서 제거합니다. 그러나 이 함수는 자동으로 superview를 다시 그리도록 하지는 않음에 유의해야 합니다.

 

NSView 객체가 다른 view의 subview로 추가될때, 자동으로 viewWillMoveToSuperview: (Mac OS X) 와 viewWillMoveToWindow: 함수(Mac OS X)를 실행합니다. 여러분은 이 함수들을 오버라이드하여 새로운 superview와 윈도우에 연관된 질의를 수행할 수 있고 관련된 갱신을 수행할 수 있습니다.

 

중요 : 메모리 관린 관점에서, view hierarchy는 Cocoa의 다른 collection 객체와 같이 취급되어야 합니다. collection에 아이템이 추가될때 추가되는 아이템은 collection에 의해 retain 되어야합니다. 제거 될때는 collection에 의해 release 되어야 합니다. 

특히, addSubview: 또는 addSubview:positioned:relativeTo: (Mac OS X) 함수를 사용하여 subview를 추가할 경우, 추가되는 view는 메시지를 수신하여 해당 view를 추가하는 view에 의해서 retain 되어야 합니다. 반대로,  superview에 removeFromSuperview 메시지를 보내어 view hierarchy에서 subview를 제거할때는 release 되어야 합니다. replaceSubview:with: 함수의 동작도 동일하게, 대치되어지는 view는 release 해야하며 대치되는 view를 대신하게 되는 새로운 view는 retain 되어야 합니다. 상세한 사항은 Objective-C Memory Management 노트를 참고 하십시요.

 

 

 

Repositioning and Resizing Views

 

view의 위치를 새로이 잡거나 사이즈를 변경하는 것은 내부적으로 복잡한 연산입니다. view가 이동하거나 사이즈가 변경될때 이전에는 가려져 보이지 않았기 때문에, superview를 다시 디스플레이하는 작업이 필요하게 되는, superview의 일부를 노출시킬 수 있습니다.  사이즈 변경은 또한 superview의 레이아웃에 영향을 미칠 수 있습니다. 어떤 경우던 view의 레이아웃 변경은 변경이 알려져야 할 필요가 있는 다른 객체들에게 있어서 관심사항입니다. 여기서는 이 내용에 대해 다루기로 하겠습니다.

 

 

Moving and Resizing Views Programmatically

 

view 인스턴스가 만들어진 이 후, 여러분은 setFrame: (Mac OS X), setFrameOrigin: (Mac OS X) 그리고 setFrameSize: (Mac OS X)와 같은, 모든 frame-setting 함수들을 사용하여 만들어진 view를 프로그램적으로 이동시킬 수 있습니다. 만일 view의 사각 영역에 대한 범위가 setBounds...(UIVIew의 경우 view의 bound는 property로 정의되어 있음 : @property(nonatomic) CGRect bounds) 함수를 통해 명확하게 정의되지 않는다면, view의 사각 영역은 자동으로 새로운 프레임 크기에 맞게 갱신되어 집니다. 

 

사각 프레임을 변경하면 subview들의 사각 프레임의 크기와 위치들도 변경되야 합니다. 위치가변경된 view가 autoresizesSubViews에 대해 YES를 반환하면, 해당 view의 subivews들은 Autoresizing of subviews에서 설명하겠지만 자동으로 사이즈가 변경됩니다.

 

어떤 함수도 자동으로 변경된 view의 사각프레임을 다시 디스플레이하거나 디스플레이를 해야한다고 표시해주지 않습니다. setFrame... 같은 함수들을 사용하게 되면, 아래 코드와 같이 여러분이 직접 위치가 변경된 view에 표시하고 superview에 디스플레이가 필요하다고 알려줘야 합니다.

 

NSView *theView;  // 이 인스턴스가 이미 있다고 생각합시다.

NSRect newFrame;   // 마찬가지고 이 인스턴스도 이미 있었다고 생각하면, 

 

[[theView superview] setNeedsDisplayInRect:[theView frame]];

[theView setFrame:newFrame];

[theView setNeedsDisplay:YES];

 

이 일부의 코드는 옮겨진 view의 프레임에 디스플레이가 필요하다고 superview에 표시합니다. 그리고 theView가 새로운 사각 프레임으로 설정된 후, 거의 대부분의 경우 변경된 view에 전체 디스플레이가 필요하다고 표시합니다. setBounds...관련 함수들 또한  수신된 view를 다시 그리지 않습니다. 그러나 이들의 변경이 superview에 영향을 미치지 않기때문에, 간단하게 수신되는 view 인스턴스에 디스플레이가 필요하다고 표시 하면 됩니다.

 

 

 

Autoresizing of Subviews

 

NSView는 관련 superview의 이동이나 크기변경에 따라, subview들을 자동으로 이동하거나 크기를 변경하기 위한 메커니즘을 제공합니다.  view에 대한 autoresizing(자동 크기변경) 설정은 대부분의 어플리케이션에 적절한 동작을 제공합니다. Autoresizing은 view가 프로그램적으로 생성될때 기본적으로 활성화되어 있습니다. 하지만 setAutoresizesViews: 함수를 통해 해당 기능을 비활성화 시킬 수도 있습니다.

 

Interface Builder의 Size inspector(Inspector의 Size 탭)에서 그래픽적으로 view의 autoresizing mask를 설정할 수 있으며, Size inspector의 테스트 모드에서 autoresizing의 효과가 어떻게 반영될 것인지 즉시 볼 수있습니다.

 

물론 autoresizing mask는 프로그램적으로도 설정할 수 있습니다.

 

view의 autoresizing mask는 autoresizing mask 상수들을 bitwise OR 연산으로 구성하여 setAutoresizingMask: 메시지에 인자 값으로 담아 보내어 정의합니다. 아래 List 1은 가각의 mask 상수와 view의 resizing 동작에 어떻게 영향을 주는지를 설명합니다.

 

List 1 Autoresizing mask content

 

- Autoresizing Mask : NSViewHeightSizable

이 값을 설정하면 view의 높이가 superview의 높이에 비례해서 변경됩니다. 그렇지 않으면, view의 높이가 superview의 높이에 비례하여 변경되지 않습니다.

 

- Autoresizing Mask : NSViewWidthSizable

이 값의 설정은, view의 높이가 superview의 높이에 비례해서 변경되도록합니다. 그렇지 않으면, view의 넓이가 superview의 넒이에 비례하여 변경되지 않습니다.

 

- Autoresizing Mask : NSViewXMinMargin

이 값을 설정하면, superview의 변경에 비례하여 view의 좌측 가장자리 위치가 조정됩니다. 그렇지 않으면 superview의 좌측 가장자리에 대하여 동일한 위치에 유지 됩니다.

 

- Autoresizing Mask : NSViewXMaxMargin

이 값을 설정하면, superview의 변경에 비례하여 view의 우측 가장자리 위치가 조정됩니다. 그렇지 않으면 superview의 우측 가장자리에 대하여 동일한 위치에 유지 됩니다.

 

- Autoresizing Mask : NSViewMinYMargin

이 값이 설정되어 있으면서 superview가 flip되지 않는 다면, view의 상단 가장자리가 superview의 높이 변경에 따라 비례하여 위치가 조정됩니다. 그렇지 않으면 superview의 상단 가장자리에 대하여 동일한 위치가 유지 됩니다. 

이 값이 설정된 상태에서 superview가 flip 되어진다면, view의 아래쪽 가장자리 위치가 superview의 높이 변경에 따라 조정됩니다. 값을 설정하지 않은 상태로  superview가 flip 된다면, view의 아래쪽 가장자리가  superview에 대햐여 동일하게 유지됩니다.

 

- Autoresizing Mask : NSViewMaxYMargin

이 값이 설정된 상태에서 superview가 flip 되지 않는다면, view의 아래쪽 가장자리 위치가 superview의 높이 변경에 따라 조정됩니다. 값을 설정하지 않은 상태로  superview가 flip 된다면, view의 아래쪽 가장자리가  superview에 대햐여 동일하게 유지됩니다.

이 값이 설정되어 있으면서 superview가 flip 되어진다면 다면, view의 상단 가장자리가 superview의 높이 변경에 따라 비례하여 위치가 조정됩니다. 그렇지 않으면 superview의 상단 가장자리에 대하여 동일한 위치가 유지 됩니다. 

 

예를 들어, view를 superview의 왼쪽 아래 모서리에 유지하고 싶다면, Autoresizing Mask를 NSViewMaxXMargin|NSViewMaxYMargin으로 정의합니다. 중심 축을 기준으로 하나이상의 면을 부드럽게 변하게 하려면, 사이즈 변경된 양이 각각의 면에 균등하게 나뉘어져야 합니다. 그림 3은 일반 superview와 flip되는 superview에서 상수 값들의 위치를 그래픽적으로 설명하고 있습니다.

 

 

[그림 3] View autoresizing mask 상수들

 

실재 Interface Builder에서 여러분이 관련 상수를 조정하여 보여지는 효과를 예측해 볼 수 있을 것입니다.

 

[그림 4] Inspector의 Size 탭 내의 Autoresizing 설정 및 확인

 

 

 

주의 : 만일 InterfaceBuilder에서 만들어진 view의 autoresizing flag들을 view의 inspector에서 설정하지 않는다면 , setAutoresizesSubviews: 메시지에 자동적으로 NO가 설정됩니다. 프로그램 적으로 autoresizing mask를 수정하기 전에 명시적으로 setAutoresizesSubviews: 메시지에 YES 값으로  인자값을 정의해 superview에 전달함으로써 autoresizing을 활성화해야 할 것입니다.

 

여러분이 view의 autoresizing을 해지하면, 해당 view의 모든 자식 view들이 superview의 변경에서 보호됩니다. 그러나 해당 view의 subview를 변경하면 그 밑으로는 autoresize mask의 설정에 따르게 됩니다. 유사하게, subview가 autoresize mask를 가지고 있지 않다면, 크기가 변경되지 않을 것이고 따라서 해당 subview의 subview들도 변경되지 않을 것입니다.

 

subclass는 view의 autoresizing 동작을 새로이 정의하기 위해서 resizeSubviewsWithOldSize: 혹은 resizeWithOldSuperviewSize: 함수를 오러바이드 할 수 있습니다. view의 resizeSubviewsWithOldSize: 함수는 해당 view의 프레임 사이즈가 변경될때 마다 자동으로 호출됩니다. 그리고 이 함수는 각각의 subview들에게 resizeWithOldSuperviewSize: 메시지를 전달합니다. 각각의 subview는 이전의 프레임사이즈를 새로운 프레임사이즈와 비교하고 위치와 크기를 자신의 autoresize mask에 따라 조정합니다.

 

중요 : autoresizing에는 몇가지 유의해야할 상항들이 있습니다. autoresizing가 정확하게 동작하기 위해서는 subview가 온전히 자신의 superview 프레임내에서 autoresize 되어야 합니다. 회전된(rotated) view에서는 autoresizing은 작동하지 않습니다. 회전된 Subview는 변경되지 않은 superview 내에서 autoresize 할 수 있으나, 해당 subview들의 자손들은 autoresize되지 않습니다.

 

 

 

Notifications

 

자신의 subview의 크기 변경을 넘어, 기본적으로 NSView 인스턴스는 자신의 경계와 사각 프레임의 변경이 발생하면 이를 주시하는 observer들에게 notification을 보냅니다. notification 이름은 각각NSViewFrameDidChangeNotification과 NSViewBoundsDidChangeNotification 입니다. (Mac OS X)

 

자신의 디스플레이가 자신의 subview를 기반으로 하는  NSView의 인스턴스는 자신을 이러한 subview들의 observer로 등록하고 subview들이 이동하거나 크기가 변경될때 마다 스스로를 갱신해야 합니다. NSScrollView와 NSClipView 인스턴스 모두 view의 스크롤러의 스크롤 조절을 이런 방식으로 합니다. 

 

기본적으로, 프레임과 사각 영역의 변경은 모두 view 인스턴스에 보내어 집니다. setPostsFrameChangedNotifications:와 setPostsBoundsChangedNotifications: 메시지에 NO의 인자값을 전달함으로써 NSView의 인스턴스가 notification을 제공하는 것을 막을 수 있습니다. 만일 어플리케이션이 view 배치가  복잡하다면, 배치전에 notification 옵션을 끄고 완료 후 복원하는 것이 성능의 향상을 가져올 수 있습니다. 모든 performance tuning이 그렇듯, 변경 notification이 성능에 부정적인 영향을 준다면 제일 먼저 고려해 봐야 할 사항입니다.

 

 

 

 

Hiding Views

 

여러분은 Cocoa 어플리케이션의 view를 NSView 함수 setHidden: 를 사용하여 감추거나 보이게 할 수 있습니다. 이 함수는 Boolean 인자를 취합니다. YES는 메시지를 수신한 view를 보이지 않도록하며, NO는 메시지를 수신한 View를 보이게 합니다.

 

setHidden: (NSView와는 다르게  UIView의 경우 hidden 속성을 boolean property로 제공합니다.)함수를 사용해 view를 숨기겨 윈도우에서 보이지 않고 이벤트를 수신하지 못하더라도 해당 view는 view hierarchy에 유지됩니다.  숨겨진 view는 해당 view의 superview의 subview 목록에 남아있게 되고 autoresizing에 참여하게 됩니다. 숨겨진 view로 표시된 view가 subview를 가지고 있다면, subview와 subview의 자식들도 숨겨집니다. 여러분이 view를 숨기면 Application Kit은 cursor, tool-tip 또는 view와 관련된 추적을 비활성화 시키게 됩니다. 

 

현재 윈도우의 첫번째 Responder인 view가 숨겨지면 다음으로 유효한 key view(nextValidKeyView 메시지를 보내어 획득 할 수 있습니다.)가 새로운 첫번째 responder가 됩니다. 숨겨진 view는 view의 nextKeyView 체인이 현재 가르키는 지점의 이전 부분으로 남아있게 되지만 키보드 네비게이션 동안 무시됩니다.

 

NSView에 정의되있는 isHidden 혹은 isHiddenOrHasHiddenAncestor 메시지를 보냄으로써 view의 숨겨진 상태를 알아볼 수 있습니다. 전자의 함수는 setHidden: 메시지로 명시적으로 숨겨진 view일 때, YES를 반환합니다. 후자는 숨김 표시가된 view의 자손일 경우에도 YES를 반환합니다.

 

주의 : Mac OS X ㅍ10.3 이전 버전에서 view를 숨기기 위해서는 superview로 부터 제거하고 후에 view hierarchy에 재 삽입하기 위해서 이것을 유지하고 있어야 했습니다. 이 접근방법은 view를 view의 hierarchy에서 분리하는 것으로 제약이 있을 수 밖에 없습니다. superview의 크기가 변경되면 제거된 view가 재 삽입될때 새로운 크기에 맞게 자동으로 조절되지 못합니다. 추가적으로, 제거된 view가 key view 체인의 일부분일 경우,  재 삽입시 체인에 다시 합쳐져야합니다. 이것은 응용프로그램이 프로그램적으로 풀어야할 문제입니다.

 

 

 

Converting Coordinates in the View Hierarchy

 

다양한 경우, 특히 이벤트를 처리할때, 어플리케이션은 view의 사각영역이나 위치를 하나의 NSView 인스턴스의 좌표 시스템에서 같은 윈도우의 다른 것(일반적으로 superview 혹은 subview)으로 전환 할 필요가 있습니다. NSView 클래스는 어느 방향으로 사각영역, 점, 그리고 크기를 변환하는 여섯가지 함수들을 정의하고 있습니다.

 

List 2 

- 지정된 view에서 메시지 수신자에 맞도록 값을 전환하는 함수

convertPoint:fromView:

convertRect:fromView:

convertSize:fromView:

 

- 메시지 수신자에서 지정된 view에 맞도록 값을 전환하는 함수

convertPoint:toView:

convertRect:toView:

convertSize:toView:

 

convert...:fromView 함수들은 두번째 파라미터로 전달된 view의 좌표시스템에서 메시지 수신자의 좌표시스템으로 값들을 전환합니다. 만일 두번째 파라미터에 nil이 전달된다면, 윈도우의 기본 좌표 시스템 값들로 간주되어 지고 값들을 메시지 수신자의 좌표시스템으로 전환합니다. convertPoint:fromView:함수는 일반적으로 아래 코드와 같이, 윈도우에 관련해서 NSEvent로 전달되어지는 mouse-event 좌표들을 메시지를 수신하는 view에 관한 좌표로 전환하기 위해 사용됩니다. 

 

1. -(void)mouseDown:(NSEvent*)event

2. {

3.      // convert the click location into the view coords

4.      clickLocation = [self convertPoint:[event locationWindow] fromView:nil];

5.      // do something with the click location

6. }

 

convert..:toView: 함수들은 반대로 동작합니다. 수신자의 좌표시스템을 매개변수로 전달되는 view의 좌표시스템으로 전환합니다. 매개변수로 전달되는 view가 nil 일 경우, 값들은 수신자의 윈도우 기본 좌표시스템으로 전환됩니다.

 

화면 촤표시스템에서, 그리고 화면 좌표시스템으로 전환하기 위해, NSView는 convertBaseToScreen:과 convertScreenToBase: 함수들을 정의하고 있습니다.  이러한 NSView의 전환 함수를 사용하는 것은, 아래 코드와 같이 단지 두 메시지만을 가지고, view의 좌표시스템과  화면의 좌표시스템간의 기하학적인 구조를 전환할 수 있도록해줍니다. 

 

NSPoint pointInWindowCoordinates:

NSPoint pointInScreenCoords:

 

pointInWindowCoordinates = [self convertPoint:viewLocation toView:nil];

pointInScreenCoords = [[self window] convertBaseToScreen:pointInWindowCoordinates];

 

view가 회전될때 혹은 단지 위치를 처리할때 전환은 간단합니다. 서로다른 회전에서 view들 간의 사각형 혹은 크기 전환은 기하학적인 구조가 합리적인 방법으로 변경되어야 합니다. 사각형을 전환할때. NSView 클래스는 가지고 있던 원래 화면 영역의 범위를 보장해야한다는 가정을 세웁니다. 이를 위해서, 전환된 사각형은 알맞은 view에 위치할때 원래 사각형을 완전히 보장하기 위해  크기가 커집니다. 

 

그림 5는  ratatedView 객체의 좌표시스템내 사각형의 해당 superview(outerView)로 전환을 보여주고 있습니다. 

 

그림 5 rotate된 view에서 값의 전환

 

크기 전환에서, NSView는 이것을 하나의 view에서 다른 view로 전환할때  (0.0, 0.0)에서의  델타 오프셋으로 간단히 처리합니다. 오프셋 거리는 동일하게 유지하지만, X, Y 축의 균형은 회전에 따라 바뀝니다. 이것은 크기 변환에서 Cocoa가 항상 양의 숫자로 이루어진 크기를 반한한다는 점에서 유의 할만 합니다.