Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[승용] Building Custom Views with SwiftUI

Eric Kwon / 권승용 edited this page Aug 18, 2024 · 1 revision

레이아웃 과정

  • 부모가 자식 뷰에게 크기를 제안(propose)
  • 자식 뷰가 자기 자신의 크기 결정
  • 부모 뷰가 부모 뷰의 좌표계에 자식 뷰를 위치시킴
  • SwiftUI는 뷰의 코너를 인접한 픽셀로 깎아냄

ex)

struct ContentView: View {
	var body: some View {
		Text("Hello World")
	}
}
  • 부모 뷰(지금 상황에서는 root view)가 Text에게 크기를 제안

    • 부모 뷰가 root 뷰이기 때문에 디바이스 전체 크기를 제안
  • 자식 뷰인 Text는 고맙지만 나는 딱 Hello World를 그려낼 만큼의 크기만 필요하다고 응답

    • SwiftUI에서는 자식 뷰의 크기를 강제시킬 방법이 없다.
  • 부모 뷰(root view)는 자식 뷰를 좌표계 안에 위치시킴

  • 뷰는 자기 자신의 크기를 결정하는 과정이 있음

    • frame, aspectratio 등 명시적인 모디파이어
    • Text등 그 내용을 자기 자신의 크기로 삼는 뷰 등
  • 그리고 SwiftUI는 뷰의 코너를 가장 인접한 픽셀로 깎아내 선명한 모서리를 만들어낸다.

  • 좀 더 복잡한 예시

Screenshot 2024年08月18日 at 12 38 48 AM
  • root view가 전체 크기를 background view에게 제안

  • background view는 레이아웃 중립적이기 때문에 해당 크기 제안을 padding view에게 그대로 전달

  • padding 뷰는 child로부터 10 포인트를 추가해야 함을 알기 때문에 그만큼을 뺀 크기를 child에 전달

  • Text 뷰는 필요한 너비를 설정 후 padding 뷰에 반환한다.

  • padding 뷰는 child보다 각 면에서 10포인트 더 커야 한다는 것을 알고, text를 자신의 좌표 공간에 적절하게 배치한다.

  • background는 레이아웃 중립적이기 때문에 padding의 크기를 부모 뷰로 전달

    • 그 전에 Color 뷰에도 그 크기를 제공
    • Color 뷰는 레이아웃에 굉장히 순응적이기 때문에 제공된 크기를 그대로 받아들임 -> 따라서 Color 뷰의 크기는 padding 뷰의 크기와 동일함
  • root 뷰는 background의 크기를 전달받고, 자신의 좌표계 안에 child 뷰(background veiw)를 위치시킴

  • frame은 제약조건이 아니라, 액자의 프레임처럼 그저 뷰일 뿐

Screenshot 2024年08月18日 at 1 11 16 AM
  • frame은 자식 뷰에게 크기를 제안하지만, 크기를 결정하는 주체는 자식 뷰이다.

  • 따라서 위와 같이 이미지 뷰에 frame을 적용해도 이미지 크기가 변하지 않는 것은 자연스럽고 의도된 것

  • 이는 SwiftUI는 UIKit보다 가벼운 방식으로 동작하며, 제약조건이 부족하거나 과도할 수 없고 표현할 수 있는 모든 것이 명확한 효과를 가진다.

  • 따라서 결과물이 마음에 들지 않을 수는 있어도, 잘못된 레이아웃이라는 것은 없다.

  • SwiftUI에서 VStack, HStack 등은 spacing을 지정하지 않을 경우 HIG에 맞춰 자동으로 spacing이 주어짐

  • SwiftUI는 앱의 국제화 지원 시, 오른쪽에서 왼쪽으로 읽는 언어를 지원할 땐 자동으로 좌표계를 뒤집음

    • 이것이 left, right 대신 leading, trailing을 사용하는 이유

Stack 알아보기

Screenshot 2024年08月18日 at 2 10 10 AM
  • 지금까지 살펴본 뷰들은 자식 뷰들이 선형적으로 연결된 형태였다면, 스택은 자식들이 동일한 조건에서 공간을 놓고 경쟁해야 한다는 점이 다르다.
  • 먼저 스택은 내부적 spacing 요구사항을 살펴보고 스택에게 제안된 크기로부터 그만큼을 제외한 미할당 공간(자식들을 위한)을 만든다.
  • 그리고 해당 공간들을 자식 뷰들의 갯수로 균등하게 나눈 후 나눠진 크기를 자식 뷰 중 가장 덜 유연한 뷰에게 제안한다.
  • Image 뷰가 고정된 크기를 가지기 때문에 여기서는 가장 덜 유연하다.
  • Image 뷰가 확정한 자기자신의 크기만큼 미할당 공간에서 제외하고, 나머지 남은 미할당 공간 크기에서 위 단계를 반복한다.
  • 이렇게 모든 자식 뷰들의 크기가 결정되면 그 후에 지정한 spacing을 사용해 정렬하고
  • 할당된 alignment를 사용해 정렬한다.
  • 마지막으로 스택은 스스로의 크기를 자식 뷰들을 정확히 감싸는 크기로 선택한 후 뷰모 뷰에게 전달한다.

layout priority 알아보기

  • 한정된 스택 공간에서 Delicous / Avocado Toast 등은 linelimit(1)을 가지기 때문에 끝이 truncated된다.
  • 이 때 Delicious가 먼저 크기를 결정하기 때문에 Avocado Toast만 truncated 될 수도 있다.
  • 이를 방지하기 위해서는 layout priority를 올려줄 수 있다.
Screenshot 2024年08月18日 at 2 28 10 AM
  • layout priority가 서로 다른 자식 뷰를 스택이 감쌀 때는
  • 먼저 낮은 우선순위의 뷰들의 가장 작은(minimum) 공간을 할당하고
  • 나머지 공간을 가장 높은 우선순위 뷰 부터 할당한다.

alignment 알아보기

  • .lastTextBaseline 사용하면 서로 다른 font의 텍스트 baseline 맞출 수 있음
Screenshot 2024年08月18日 at 3 19 20 AM
  • alignmentGuide 사용하면 다른 baseline에 대해 percentage로 지정 가능
Screenshot 2024年08月18日 at 3 19 10 AM
  • HStack, VStack에 대해 커스텀 alignment 지정 가능
Screenshot 2024年08月18日 at 3 21 53 AM

SwiftUI에서의 drawing

  • SwiftUI는 뷰와 drawing이 사실상 동일한 방식으로 동작 (통합)

    • UIKit에서는 Core Graphics등을 사용해 drawing하는 것이 가능
    • 그러나 SwiftUI는 그러한 drawing은 뷰를 만드는 것과 동일
    • 따라서 Shape과 같은 drawing에도 레이아웃, 애니메이션, 필터 효과 등의 모디파이어들이 똑같이 적용!
  • Shape 프로토콜을 준수하는 커스텀 Shape을 만들 수 있음

  • drawingGroup을 사용하면 모든 SwiftUI 뷰를 하나의 NSViewer UI View로 flatten 시켜서 metal을 사용해 렌더링하도록 할 수 있다.

    • 성능 향상시킬 수 있음

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /