SwiftUI에서 ForEach와 Identifiable 프로토콜 활용하기
✅ SwiftUI에서 리스트를 다룰 때 필수적인 ForEach와 Identifiable
SwiftUI에서는 ForEach와 Identifiable 프로토콜을 활용하여 반복적인 UI 요소를 효율적으로 만들 수 있습니다. 특히, List나 VStack, HStack 등에서 여러 개의 데이터를 표시할 때 유용합니다.
이 글에서는 ForEach와 Identifiable 프로토콜의 개념과 활용 방법을 자세히 설명하겠습니다.
1️⃣ ForEach란 무엇인가?
ForEach는 SwiftUI에서 반복적으로 뷰를 생성하는 데 사용되는 구조체입니다. Swift의 for-in 루프처럼 동작하지만, SwiftUI의 선언형 문법에 맞게 설계되었습니다.
📌 기본 문법
ForEach(컬렉션, id: \.키) { 요소 in
// 반복할 뷰
}
• 컬렉션: 배열(Array) 또는 범위(Range)를 사용할 수 있습니다.
• id: \.키: 각 요소를 식별하는 고유한 값(ID)입니다.
• { 요소 in ... }: 각 요소에 대해 실행할 뷰를 정의합니다.
2️⃣ ForEach를 활용한 기본 예제
배열을 사용하여 간단한 리스트를 만들 수 있습니다.
import SwiftUI
struct ContentView: View {
let fruits = ["🍎 사과", "🍌 바나나", "🍇 포도", "🍉 수박"]
var body: some View {
VStack {
Text("과일 리스트")
.font(.title)
.padding()
ForEach(fruits, id: \.self) { fruit in
Text(fruit)
.font(.headline)
.padding()
}
}
}
}
📝 코드 설명
1. fruits 배열에 과일 이름을 저장합니다.
2. ForEach(fruits, id: \.self)를 사용하여 각 과일을 리스트에 출력합니다.
3. id: \.self를 사용하여 문자열을 직접 고유 식별자로 활용합니다.
📌 주의: 배열의 요소가 String, Int 같은 값 타입일 경우, id: \.self를 사용하여 고유성을 보장할 수 있습니다. 하지만, 사용자 정의 모델 객체일 경우 Identifiable 프로토콜을 구현하는 것이 더 좋습니다.
3️⃣ Identifiable 프로토콜을 활용한 데이터 리스트
배열에 String 같은 기본 타입이 아닌, 사용자 정의 데이터 모델을 사용할 경우에는 각 항목을 고유하게 식별할 방법이 필요합니다.
이때 Identifiable 프로토콜을 채택하면 id를 자동으로 인식하여 ForEach에서 id: \.self를 명시할 필요가 없습니다.
📌 Identifiable 프로토콜 구현 예제
import SwiftUI
// Identifiable 프로토콜을 준수하는 데이터 모델
struct Fruit: Identifiable {
let id = UUID() // 고유한 ID
let name: String
}
struct ContentView: View {
let fruits = [
Fruit(name: "🍎 사과"),
Fruit(name: "🍌 바나나"),
Fruit(name: "🍇 포도"),
Fruit(name: "🍉 수박")
]
var body: some View {
VStack {
Text("과일 리스트")
.font(.title)
.padding()
List(fruits) { fruit in
Text(fruit.name)
.font(.headline)
}
}
}
}
📝 코드 설명
1. Fruit 구조체가 Identifiable 프로토콜을 채택합니다.
• id 속성을 UUID()로 설정하여 각 객체가 고유한 ID를 가집니다.
2. fruits 배열은 Fruit 객체의 리스트입니다.
3. List(fruits) { fruit in ... } 형태로 ForEach 없이도 리스트가 자동으로 생성됩니다.
• Identifiable을 준수하기 때문에 id: \.self를 명시할 필요가 없습니다.
📌 Tip: Identifiable을 사용하면 UUID()뿐만 아니라, 데이터베이스의 고유 ID(예: 사용자 ID, 제품 코드)도 사용할 수 있습니다.
4️⃣ ForEach와 Identifiable을 활용한 동적 UI 예제
아래 예제에서는 사용자가 직접 데이터를 추가할 수 있는 리스트를 만들어 보겠습니다.
import SwiftUI
struct Task: Identifiable {
let id = UUID()
let title: String
}
struct ContentView: View {
@State private var tasks: [Task] = []
@State private var newTask: String = ""
var body: some View {
VStack {
Text("할 일 목록")
.font(.title)
.padding()
HStack {
TextField("할 일을 입력하세요", text: $newTask)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button(action: {
if !newTask.isEmpty {
tasks.append(Task(title: newTask))
newTask = "" // 입력 필드 초기화
}
}) {
Text("추가")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
}
List(tasks) { task in
Text(task.title)
}
}
.padding()
}
}
📝 코드 설명
1. Task 구조체가 Identifiable을 준수하여 id를 자동 인식합니다.
2. @State를 사용하여 tasks 배열을 동적으로 관리합니다.
3. TextField에서 입력받은 값을 tasks 배열에 추가하는 기능을 구현합니다.
4. List(tasks) { task in ... } 형태로 리스트를 동적으로 렌더링합니다.
5️⃣ ForEach에서 인덱스 활용하기
ForEach는 enumerated() 메서드와 함께 사용하면 인덱스를 활용할 수도 있습니다.
let items = ["🍕 피자", "🍔 버거", "🍣 초밥"]
ForEach(Array(items.enumerated()), id: \.element) { index, item in
Text("\(index + 1). \(item)")
}
📌 Tip: id: \.element를 사용하여 각 항목을 고유하게 식별합니다.
✨ 마무리
SwiftUI에서 ForEach와 Identifiable은 리스트 형태의 UI를 만들 때 필수적인 개념입니다.
✅ 핵심 정리
• ForEach는 컬렉션의 각 요소를 반복하여 뷰를 생성합니다.
• 값 타입(String, Int)을 사용할 경우 id: \.self를 지정해야 합니다.
• 사용자 정의 데이터 모델을 사용할 경우 Identifiable 프로토콜을 채택하여 id를 설정하는 것이 좋습니다.
• ForEach를 활용하여 동적 UI를 구성하고, 리스트를 효율적으로 관리할 수 있습니다.