[SwiftUI] ForEach 너도 View냐?

룰루날라·2022년 5월 19일
2
post-custom-banner

SwiftUI에서는 반복해서 뷰를 만들기 위해 ForEach를 많이 사용한다.

위와 같이 배열 emojis를 넘겨주고, 각 요소를 유일하게 식별할 수 있도록 id값을 알려주면 해당 데이터를 활용해 View를 반복해서 생성해준다.

for-in문을 쓰면 되잖아???

뭔가를 ‘반복’하는 거라면 쉽게 반복문을 써주면 될 것 같은데 왜 ForEach라는 것을 쓰는 걸까?
한 번 for-in문을 사용해 view를 생성해보자.

for-in문이 우리에게 익숙하다보니 훨씬 코드가 쉽게 느껴진다. 뭔가 더 깔끔한 것 같은데…?
하지만 for-in문 뒤로 희미하게 비춰지고 있는 빨간 줄이 보이는가

사실 에러가 나는 코드였다ㅎㅎ
에러가 나는 이유는 에러 문구 그대로다

Closure containing control flow statement cannot be used with result builder ‘ViewBuilder’
→ 조건문을 포함하는 클로저는 result builder인 ‘ViewBuilder’와 함께 쓰일 수 없다.

ViewBuilder가 무엇인지 잘 모르기에 읽자마자 이해하기는 어렵지만, 간단히 말하면 ViewBuilder에서는 조건문을 쓸 수 없다는 말이다.

VStack의 이니셜라이저를 보면서 그 이유를 확인해보자.

VStack의 이니셜라이저를 보면 VStack의 클로저는 Content를 리턴해야 한다.
Content는 일종의 뷰로, VStack의 클로저 즉 ViewBuilder내에서는 View만 리턴할 수 있다.
그런데 지금은 for-in문을 돌리고만 있기 때문에! 에러가 나는 것이었다.
ViewBuilder가 무엇인지 궁금하니 요 내용에 대해서는 다음에 더 알아보도록 하자ㅎㅎ

그래서 ForEach란 무엇일까?

공식문서상의 정의를 살펴보자면,

식별된 데이터의 콜렉션으로부터 요구에 따라 뷰를 계산해주는 구조체..🤨

무슨 말인지 이해가 잘 안 간다ㅎㅎㅎ
하지만 잘 살펴보면 정의에 나와있는 단어들은 선언부와 모두 매칭이 된다.

  • 식별된 데이터의 -> ID : Hashable
  • 콜렉션으로부터 -> Data : RandomAccessCollection
  • 요구에 따라 뷰를 계산 -> Content (Content는 클로저다!)

무엇을 이야기하는건지 하나하나 살펴보자.

Parameters

ForEach 인스턴스를 만들기 위해서는 위 3개의 파라미터가 필요하다.

  • data: ForEach 인스턴스가 뷰를 만드는 데 사용하는 데이터
  • id: data를 식별하기 위한 id 값
  • content: 뷰를 생성하는 view builder

처음 봤던 이미지를 다시 보면서 이 파라미터들을 이해해보자.

  • data: 각 카드뷰를 만들기 위해 필요한 이모티콘 데이터를 배열 emojis로 넣어준다.
  • id: emojis배열의 각각의 요소를 식별하기 위해 id값을 전달해준다.
  • content: 어떤 뷰를 만들지 요구사항을 클로저로 전달한다.

어떤 느낌인지 조금씩 감이 오는 것 같다!

Identifiable

그런데 아직 의문이 남는 부분이 있다. id값은 대체 왜 넣어주는 걸까?

SwiftUI는 효율적으로 뷰를 새로 그리기 위해 바뀐 부분만 새로 그리기때문이다.
전달받은 데이터에서 어떤 것이 추가되거나 삭제됐는지 눈치채 바뀐 부분만 새로 그려야 하기 때문에 각각의 요소를 구분하기 위해서는 id가 필요하다.

id값을 전달하는 방법은

  • Identifiable 프로토콜을 사용하거나
  • keypath를 사용한 id를 파라미터로 전달하는 방식

두 가지가 있다.

ForEach는 View다

많은 이야기를 했지만, ForEach는 결국 View다.

ForEach가 채택하고 있는 프로토콜들을 보면, View가 있는 걸 확인할 수 있다.

그렇기 때문에 VStack의 클로저 안에서 바로 ForEach를 리턴할 수 있었던 것이다.

다시 공식문서상의 ForEach의 정의를 읽어보자

식별된 데이터의 콜렉션으로부터 요구에 따라 뷰를 계산해주는 구조체

이제 조금은 더 이 문장이 와닿을까?

앞으로는 ForEach가 계산을 통해 여러 뷰를 만들어주는 역할을 하는 구조체이자, 그 자체로 뷰라는 생각을 가지고 코딩을 해야겠다~.~




참고
https://developer.apple.com/documentation/swiftui/foreach
https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-views-in-a-loop-using-foreach
https://swdevnotes.com/swift/2021/for-loop-in-swiftui/

profile
즐거운 인생 (~-_-)~ ~(-_-~)
post-custom-banner

0개의 댓글