SwiftUI에서는 반복해서 뷰를 만들기 위해 ForEach
를 많이 사용한다.
위와 같이 배열 emojis
를 넘겨주고, 각 요소를 유일하게 식별할 수 있도록 id값을 알려주면 해당 데이터를 활용해 View를 반복해서 생성해준다.
뭔가를 ‘반복’하는 거라면 쉽게 반복문을 써주면 될 것 같은데 왜 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가 무엇인지 궁금하니 요 내용에 대해서는 다음에 더 알아보도록 하자ㅎㅎ
공식문서상의 정의를 살펴보자면,
식별된 데이터의 콜렉션으로부터 요구에 따라 뷰를 계산해주는 구조체..🤨
무슨 말인지 이해가 잘 안 간다ㅎㅎㅎ
하지만 잘 살펴보면 정의에 나와있는 단어들은 선언부와 모두 매칭이 된다.
ID : Hashable
Data : RandomAccessCollection
Content
(Content는 클로저다!)무엇을 이야기하는건지 하나하나 살펴보자.
ForEach 인스턴스를 만들기 위해서는 위 3개의 파라미터가 필요하다.
data
: ForEach 인스턴스가 뷰를 만드는 데 사용하는 데이터id
: data를 식별하기 위한 id 값content
: 뷰를 생성하는 view builder처음 봤던 이미지를 다시 보면서 이 파라미터들을 이해해보자.
data
: 각 카드뷰를 만들기 위해 필요한 이모티콘 데이터를 배열 emojis
로 넣어준다.id
: emojis
배열의 각각의 요소를 식별하기 위해 id값을 전달해준다.content
: 어떤 뷰를 만들지 요구사항을 클로저로 전달한다.어떤 느낌인지 조금씩 감이 오는 것 같다!
그런데 아직 의문이 남는 부분이 있다. id
값은 대체 왜 넣어주는 걸까?
SwiftUI는 효율적으로 뷰를 새로 그리기 위해 바뀐 부분만 새로 그리기때문이다.
전달받은 데이터에서 어떤 것이 추가되거나 삭제됐는지 눈치채 바뀐 부분만 새로 그려야 하기 때문에 각각의 요소를 구분하기 위해서는 id가 필요하다.
id값을 전달하는 방법은
Identifiable
프로토콜을 사용하거나 id
를 파라미터로 전달하는 방식두 가지가 있다.
많은 이야기를 했지만, 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/