개발하는 뚝딱이

[iOS] View Programming 뷰 프로그래밍 본문

iOS

[iOS] View Programming 뷰 프로그래밍

개발자뚝딱이 2020. 3. 19. 20:43

'뷰'와 '윈도우' 구조

뷰와 윈도우는 UI를 보여주고 인터페이스와 상호작용하도록 구현되어있습니다. UIKit과 다른 프레임워크는 수많은 뷰를 지원하고, 커스터마이징 또한 할 수 있습니다. 뷰를 잘 사용하기 위해선 UIView와 UIWindow 클래스를 잘 이해해야 합니다.

 

 

뷰 아키텍처의 기본

대부분 화면에서 보여지는 것은 UIView 클래스의 뷰 객체입니다. 뷰 객체는 창에서 사각형 형태로 정의되며, 그 사각형 내에서 발생하는  드로잉이나 터치 등의 이벤트를 처리합니다. 뷰는 다른 뷰의 상위 뷰가 될 수 있으며, 배치나 사이즈 또한 조정이 가능합니다. UIView 클래스가 하는 대부분의 일은 뷰 사이의 관계를 관리하는 것이지만, 개발자가 변경이 가능합니다.

 

뷰는 코어 애니메이션 계층과 함께 작동하며 뷰 컨텐츠의 렌더링과 애니메이션을 처리합니다. UIKit의 모든 뷰는 백업, 뷰와 관련된 애니메이션 관리를 레이어 객체의 지원을 통해 받습니다. 대부분의 동작은 UIView 인터페이스를 통해 동작합니다. 그러나, 렌더링이나 애니메이션과 같이 제어가 더 필요한 경우에, 해당 레이어에 의해서 동작할 수 있습니다.

 

뷰와 레이어 사이의 관계를 이해하기 위해, 위 그림을 살펴봅시다. 뷰는 윈도우와 컨테이너뷰, 이미지뷰, 툴바를 포함한 UIView 객체와 윈도우를 포함하고 있습니다. 모든 뷰는 상응하는 레이어 객체를 가지고 있어 레이어 객체를 통해 뷰의 레이어 속성에 접근할 수 있습니다. (바 버튼은 뷰가 아니기 때문에 레이어 객체에도 접근할 수 없습니다) 레이어 객체 뒤에는 코어 애니메이션 렌더링 객체와 화면의 비트를 관리하는 하드웨어 버퍼가 있습니다.

코어에니메이션 레이어 객체는 성능에 중요한 영향을 끼칩니다. 뷰의 객체를 그리는 코드는 최소한으로 호출이 되는데, 코드가 호출될 때 그 결과는 코어 애니메이션에 캐싱이 되고 이후에 재사용됩니다. 원래는 뷰를 업데이트하기 위해 뷰를 비용이 큰 드로잉 싸이클이 렌더링된 컨텐츠를 재사용하면서 필요없어지게 되었습니다. 뷰를 재사용하는 것은 새로운 컨텐츠를 만드는 것보다 훨신 비용이 적게 들기 때문입니다.

 

 

뷰의 계층구조와 서브뷰 관리

컨텐츠를 화면에 보여주기 위해, 뷰는 다른 뷰의 컨테이너로 사용이 됩니다. 한 뷰가 다른 뷰를 포함하면 부모-자식 간의 관계가 생깁니다. 다른 말로, 부모뷰-자식뷰슈퍼뷰-서브뷰라고도 합니다. (혹은 상위뷰-하위뷰)

 

이 관계는 뷰가 보여지는 순서에 영향을 미칩니다. 서브뷰는 슈퍼뷰의 내용을 가릴 수 있습니다. 만약 서브뷰가 완전히 불투명하면 서브뷰는 슈퍼뷰를 완전히 가릴 수 있고, 반투명하면 슈퍼뷰의 컨텐츠는 화면에 비쳐서 서브뷰의 컨텐츠와 함께 보여질 것입니다. 각 슈퍼뷰는 서브뷰들을 배열에 넣어서 저장하고 그 순서는 각 서브뷰에 영향을 줍니다. 만약 두 형제 서브뷰가 서로를 겹치면, 가장 최근 배열에 추가된 뷰가 화면에 보여집니다.

 

슈퍼뷰-서브뷰 관계는 뷰의 동작에도 영향을 줍니다. 슈퍼뷰의 사이즈가 바뀌면 서브뷰의 사이즈나 위치 또한 함께 바뀝니다. 슈퍼 뷰의 사이즈가 바뀌면, 개발자가 각 서브뷰의 사이즈 재조정을 컨트롤할 수 있습니다. 서브뷰에 영향을 주는 것의 다른 예로  슈퍼뷰를 숨기거나, 슈퍼뷰의 투명도가 바뀌거나, 슈퍼뷰의 좌표가 바뀌는 것 등이 있습니다.

 

뷰의 계층구조에서, 뷰의 순서는 앱이 이벤트에 응답하는 방식을 결정합니다. 특정 뷰 내에서 터치가 발생하면, 시스템은 터치 정보와 함께 이벤트 객체를 핸들링 할 수 있도록 곧바로 그 뷰에 보냅니다. 그러나 만약 뷰가 터치 이벤트를 처리하지 않으면, 이벤트 객체는 슈퍼뷰로 올라가게 되고, 슈퍼뷰 또한 처리하지 않으면, 계속 응답자 체인(Responder Chain)을 따라 이벤트를 처리하는 객체를 찾아서 올라갑니다. 특정 뷰는 이벤트 객체를 뷰 컨트롤러와 같은 중간 응답자 객체로 전달할 수도 있습니다. 만약 이벤트가 처리되지 않으면, 결국 애플링케이션 객체에 도달하고 삭제가 됩니다.

 

 

뷰의 좌표 시스템

UIKit의 기본 좌표는 왼쪽 상단에 원점을 두고, 오른쪽으로 아래쪽으로 x축과 y축을 둡니다. 좌표 값은 부동소수점으로 표현되며, 이를 통해 정확한 레이아웃이 가능하며 해상도와 관계없이 컨텐츠의 위치를 지정할 수 있습니다.

스크린 좌표 시스템 (Screen Coordinate System)외에도 윈도우와 뷰는 로컬 좌표 시스템(Local Coordinate System)이 있습니다. 이는 화면과의 관계가 아닌 뷰나 윈도우 원점과의 관계를 이용하는 시스템이 있습니다.

 

모든 뷰와 윈도우는 각각의 로컬 좌표 체계가 있기 때문에, 어떤 좌표계를 쓰는지 알아야 합니다. 드로잉의 경우 뷰 자신과의 관계로 좌표를 설정하고, 모양이 바뀔 때는 슈퍼뷰와의 관계로 좌표를 설정합니다. UIWindow와 UIView 클래스 모두 한 좌표 시스템에서 다른 좌표 시스템으로 변경하는 메소드를 갖고 있습니다.

 

프레임, 바운드, 센터의 관계

뷰 객체는 사이즈와 위치를 프레임과 바운드 센터 속성을 이용하여 정합니다.

  • 프레임 속성 Frame 슈퍼뷰의 좌표 시스템을 따라 뷰의 사이즈와 위치에 의해 지정된 프레임 사각형
  • 바운드 속성 Bound 뷰 자신의 로컬 좌표 시스템에 따라 뷰의 사이즈와 원점에 의해 지정된 경계
  • 센터 속성 Center 은 슈퍼뷰의 좌표 시스템을 따라 뷰의 중심 좌표

주로 센터와 프레임 속성은 현재 뷰의 위치나 크기를 변경할 때, 바운드 속성은 해당 뷰 내부에 그림을 그릴 때, 하위 뷰 등을 조정할 때입니다. 바운드 속성의 기본 원점은 (0,0)이며 사이즈는 프레임 사각형에 맞춰집니다. 이 사각형 안에 그려지는 것은은 컨텐츠 중의 일부이며, 바운드 사각형의 원점을 바꿀 때, 새 사각형에 그려진 것이 뷰의 컨텐츠가 됩니다.

 

아래 그림은 이미지 뷰의 프레임과 바운드 사각형 관계를 보여줍니다. 프레임 경우, 왼쪽 상단 코너는 슈퍼뷰의 좌표체계에 따라 (40, 40)에 맞춰지며 사이즈는 240 x 380 입니다. 바운드 경우, 원점은 (0, 0)이며 사이즈는 프레임에 맞춰져 240 x 380 입니다.

3개의 속성을 각각 바꾼다 하더라도, 한 속성은 다른 속성에 영향을 끼칠 수 있습니다. 

  • 프레임 속성에 따라, 바운드 사이즈가 변경됩니다. 센터 속성 또한 새 프레임 속성에 맞게 새로운 센터를 정합니다.
  • 센터 속성에 따라, 프레임의 원래 값이 함께 변합니다.
  • 바운드 속성의 사이즈에 따라, 프레임 속성의 사이즈가 바운드 사이즈에 맞춰 변경됩니다.

기본적으로, 뷰 프레임은 슈퍼뷰 프레임에 의해 잘리지 않습니다. 그래서 슈퍼뷰 밖에 있는 모든 서브뷰는 잘리지 않고 전체가 보여집니다. (그러나 슈퍼뷰의 clipsToBounds 속성을 YES로 변경하여 이 동작을 바꿔줄 수 있습니다.) 서브뷰가 잘리던 잘리지 않던, 터치 이벤트는 항상 타겟 뷰의 슈퍼뷰 바운드를 따릅니다. 즉, 슈퍼뷰의 바운드 밖에 존재하는 뷰의 터치 이벤트는 해당 뷰로 전달되지 않습니다.

 

포인트와 픽셀

iOS에서 좌표 값과 거리는 부동소수점 값을 사용합니다. 측정 사이즈는 디바이스마다 다양하며 큰 관련은 없습니다. '.' 의 주요 이해 포인트는 드로잉 동안 고정 프레임의 참조값을 제공하는 것입니다.

 

 

 

'iOS' 카테고리의 다른 글

[ios/xcode] xcode에서 위치 사용하기  (0) 2020.04.17
[iOS] 델리게이트 Delegate  (0) 2020.04.05
[iOS] 네비게이션 컨트롤러 Navigation Controller  (0) 2020.03.19
[iOS] 앱 시닝(app thinning)  (0) 2020.02.15
[iOS] 에셋 카탈로그  (0) 2020.02.15