반응형

 

Hacking with Swift 사이트의 강좌 번역본입니다.

 

[원문 : https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-views-in-a-loop-using-foreach]

 

How to create views in a loop using ForEach

 

일반적으로 SwiftUI에서 시퀀스(sequences)를 반복해서 뷰를 만드려는 경우, ForEach를 사용합니다.

 

중요: ForEach를 쉽게 보고 Swift의 시퀀스에서 사용하는 forEach() 메소드와 같다고 생각하지만, 보시다시피 그것은 사실이 아닙니다. 

 

SwiftUI에 있는 ForEach는 자체적인 뷰 구조체로 보는게 맞으며, 원하는 경우에 뷰 body에서 직접 반환할 수 있는 것을 의미합니다. 항목들의 배열을 제공하고, 값이 변경될때 업데이트 하는 방법을 알기 위해 SwiftUI에 각각 고유하게 식별할 수 있는 방법을 알려줘야 할수도 있습니다. 또한 반복문에서 각 항목에 대한 뷰를 만들기 위한 클로져를 전달합니다.

 

범위로된 간단한 반복문의 경우에, ForEach 내부로 범위를 직접 전달할 수 있고 Swift에게 각각 숫자를 고유한 식별자로 사용하도록 합니다. 예를들어, 10에서 1까지 숫자를 내려서, 끝부분에 메시지를 추가합니다.

VStack(alignment: .leading) {
    ForEach((1...10).reversed(), id: \.self) {
        Text("\($0)…")
    }

    Text("Ready or not, here I come!")
}

 

SwiftUI가 배열의 각 요소들을 고유하게 식별할 수 있는 .id(: .self) 부분이 필요합니다 - 이는 항목을 추가하거나 제거하는 경우에, SwiftUI가 정확히 어떤것인지 알고 있습니다. 

 

모든 타입의 반복을 만들기 위해 이러한 접근법을 사용할 수 있습니다. 예를들어, 다음 코드는 3가지 색상의 배열을 만들고, 전부 반복해서, 각각 색상 이름과 색상 값을 사용해서 텍스트 뷰를 만듭니다.

struct ContentView: View {
    let colors: [Color] = [.red, .green, .blue]

    var body: some View {
        VStack {
            ForEach(colors, id: \.self) { color in
                Text(color.description.capitalized)
                    .padding()
                    .background(color)
            }
        }
    }
}

 

.self를 사용해서 Swift에게 각 항목이 자체 값을 사용해서 고유하게 식별하게 되는 것을 알려줍니다. 따라서, [1, 2, 3] 배열이 있고 .self로 각 값을 식별하는 것은 첫번째 항목이 식별자 1, 두번째는 2, 세번째는 3을 가지고 있는 것을 의미합니다.

 

배열에서 사용자정의 타입을 사용하는 경우에, 타입 내부에 고유하게 식별할 수 있는 프로퍼티인 id:를 사용해야 합니다. 예를들어, 다음은 테스트 결과를 저장하는 구조체입니다.

struct Result {
    var id = UUID()
    var score: Int
}

 

고유함을 보장한다는 의미인 UUID로 된 id 프로퍼티가 있습니다 - 우리의 목적에 알맞습니다. 결과의 배열을 반복하고자하는 경우에, VStack에서 각 결과를 보여주는 텍스트 뷰를 만들고나서, 이를 사용합니다.

struct ContentView: View {
    let results = [Result(score: 8), Result(score: 5), Result(score: 10)]

    var body: some View {
        VStack {
            ForEach(results, id: \.id) { result in
                Text("Result: \(result.score)")
            }
        }
    }
}

 

SwiftUI는 id 프로퍼티를 보고 ForEach 내부에 있는 뷰들을 구별할 수 있습니다.

 

대안으로, Identifiable 프로토콜을 준수하는 Result을 만드는 경우에 ForEach(results)를 작성할 수 있습니다. 해당 프로토콜을 준수한다는 것은 각 객체를 고유하게 식별하는 id프로퍼티를 추가한다는 의미이며, 우리의 경우에는 이미 가지고 있습니다. 따라서 이 코드는 동일한 결과가 됩니다:

struct Result: Identifiable {
    var id = UUID()
    var score: Int
}

struct ContentView: View {
    let results = [Result(score: 8), Result(score: 5), Result(score: 10)]

    var body: some View {
        VStack {
            ForEach(results) { result in
                Text("Result: \(result.score)")
            }
        }
    }
}

 

반응형
Posted by 까칠코더
,