본문 바로가기

iOS/WWDC 가보자고

[WWDC 가보자고] WWDC 2019 / Building Custom Views in SwiftUI - 2

아래 내용은 WWDC영상을 보고 제 자신이 중요하다고 생각된 부분들을 정리한 글입니다.
보다 자세한 내용 혹은 전체 내용은 WWDC영상을 통해 확인하는 것을 추천드립니다.
지난 글에서는 SwiftUI에서 기본적으로 레이아웃이 어떻게 그려지는지를 정리했는데요, 이번에는 Stack이 어떻게 동작하는지를 정리하려고 합니다.

두 줄 요약 🚀

  • SwiftUI 에서 Stack이 어떤 프로세스로 레이아웃을 그리는지 알 수 있다.
  • 프로세스를 이용해서 커스터마이징 된 뷰를 만들 수 있다.

영상 링크🔗

 

Building Custom Views with SwiftUI - WWDC19 - Videos - Apple Developer

Learn how to build custom views and controls in SwiftUI with advanced composition, layout, graphics, and animation. See a demo of a high...

developer.apple.com

지난 글📄

👉  [WWDC 가보자고] WWDC 2019 / Building Custom Views in SwiftUI - 2


How Stacks Work

이전 글에서 정리했던 레이아웃의 View hierarchy는 부모 자식 관계가 linear하게 연결된 친구로만 정리를 했는데요, Stack을 사용하기 시작하면 Stack 하위에 다수의 컴포넌트들을 위치시킬 수 있으므로 수직이 아닌 수평적인 관계를 구성할 수 있습니다.

Stack의 자식들로 있는 컴포넌트들은 각각 동등한 영역을 가지기 위해 계산되어집니다.
위 말을 듣고 정확하게 무슨 말을 하는거지?? 싶었는데 아래 과정들을 보면 어느정도 이해가 될겁니다!

일단 지난 글에서 정리했던 레이아웃이 그려지는 순서는 이렇습니다.

1. 부모 뷰가 자식 뷰를 위해 사용할 수 있는 공간을 제안합니다.
2. 자식 뷰는 스스로 자신의 사이즈를 결정합니다. (Self-sizing)
3. 부모 뷰가 사이즈가 결정된 자식뷰를 자신의 공간에 위치시킵니다. 

해당 프로세스가 Stack에서도 동일하게 적용되니까 똑같이 시작해봅시다.
위 과정에서는 RootView와 같은 컴포넌트는 생략을 한 상황이고, 화살표로 그려진 영역을 Parent가 가지고 있다 라는 전제로 시작을 합니다.

계층 구조의 최상위에 있는 Parent가 자식인 HStack에게 자신이 사용할 수 있는 영역을 제안합니다.

HStack이 Parent로부터 영역을 제안받은 후 가장 처음 계산하는 영역은 HStack 자식들 사이의 간격을 먼저 계산합니다. 
위에서는 사이 간격을 특정 숫자로 고정하지 않았으므로 default 값으로 계산 됩니다.

위에서는 사이 간격을 S0, S1로 정의했고 Parent로부터 제안 받은 영역에서 계산한 간격인 S0 + S1을 빼줍니다. 
빼는 이유는 나머지 컴포넌트가 사용할 수 있는 영역들을 계산하기 위해서 입니다!
위 그림에서 사이 간격이 빠진 영역을 흰색 화살표로 표현했고, 해당 영역은 사이 간격을 제외한 나머지 컴포넌트들이 사용할 수 있는 영역이라고 정의됩니다.

그럼 다음으로는 나머지 자식들의 레이아웃 배치를 해야합니다.
부모인 HStack 입장에서는 안타깝지만 아직 자식들이 얼만큼의 영역을 차지하는지 알 수 없습니다.. 그렇기 때문에 남은 영역을 3등분을 해서 각자 자식들에게 제안합니다.
그럼 자식 3개중에 어떤 자식을 먼저 계산하러가는가?? 마찬가지로 알 수 없어서 순서대로 가거나 아무거나 갈줄 알았지만 아니였습니다!!ㅋㅋㅋ

자식들 중 가장 least flexible한 컴포넌트를 먼저 찾아갑니다. 말 그대로 영역이 최대한 고정적인 컴포넌트가 있다면 먼저 처리를 합니다.

자식은 Text 2개와 Image 1개로 이루어져 있는데요, Text는 글자 내용에 따라 유동적으로 사이즈가 변하기도 하고, 텍스트 길이보다 좁은 영역에 들어가는 상황이라면 텍스트의 일부가 truncate됩니다. 반면에 Image는 고정 사이즈를 가지는 컴포넌트입니다. 이미지 컴포넌트의 영역을 늘린다고 해서 이미지가 늘어나지 않습니다. 그러므로 3개의 자식중에 이미지 컴포넌트를 먼저 처리하러 이동합니다.

Image는 부모로 영역을 제안 받고 자신의 영역을 계산합니다. 위에서는 20*20 사이즈를 가진 이미지이므로 20*20영역의 사이즈를 계산했고 그 폭을 w로 정의했습니다.

위에서 컴포넌트 사이 간격을 구해서 제안한 영역에서 빼준것과 마찬가지로 계산된 이미지의 사이즈를 남은 영역에서 빼줍니다.
나머지 남은 영역들은 남은 두 Text 컴포넌트들에게 할당할 수 있는 영역을 나타냅니다.

다음으로 위에서 했던 과정들을 반복합니다.
남은 영역들을 아직 사이즈 처리하기 전 컴포넌트 개수인 2로 나눈 영역을 자식에게 제안합니다.
HStack의 자식들 중에서 다음으로 least flexable한 컴포넌트를 찾아 사이즈를 계산하러 가야하는데, 남은 두 자식은 똑같이 Text컴포넌트입니다! 그래서 아무에게나 가도 상관없습니다. 여기에서는 Delicious 텍스트를 가진 친구에게 먼저 가네요.

마찬가지로 텍스트 영역을 계산해줍니다. Delicious 텍스트가 들어간만큼 사이즈가 정해집니다.

남은 HStack 영역에서 계산된 Text 사이즈를 제거해줍니다. 그럼 자동으로 남은 영역은 Avocado Toast 텍스트가 사용할 수 있는 영역이겠네요!

마지막으로 남은 Text에 대해서도 위와 동일한 과정을 반복하고 HStack에게 포커싱이 돌아오면 Hstack의 모든 자식들이 사이징 과정을 완료하게 됩니다. 그럼 남은 레이아웃 프로세스인 HStack 자체 사이징을 하고 부모로 사이즈를 전달하는 과정으로 끝이납니다!

지난 글에서 기본적인 SwiftUI 레이아웃 프로세스와 이번 글에서 HStack이 동작하는 과정을 디테일하게 알아보면서 SwfitUI에 대한 기본적인 지식을 얻을 수 있게 되었습니다. 해당 영상들에서 기본적인 원리 외에도 SwiftUI에서 새롭게 선보이는 함수라든지 재미있는 기술들을 소개해 줘서 신기한 느낌으로 볼 수 있었던 것 같습니다. 위 내용보다 좀 더 디테일하게 알아보고 싶다면 영상을 직접 보는 것을 추천드립니다!