← 메인으로

0821-2 클로저

클로저는 SwiftUI랑 붙어다니는 개념이라 확실히 이해하면 뷰 짜는 게 훨씬 편해진다.

1. 클로저 기본 문법

let greet = { (name: String) -> String in return "Hello, \(name)" } print(greet("James")) 

2. 고차함수 예시(map, filter, reduce)

클로저는 컬렉션 다룰 때 특히 많이 쓴다.

  1. map: 모든 원소에 같은 동작을 적용한다.
let numbers = [1, 2, 3, 4, 5] let doubled = numbers.map { $0 * 2 } print(doubled) // [2, 4, 6, 8, 10] 
let numbers = [1, 2, 3] let doubled = numbers.map { $0 * 2 } 
{ (num: Int) -> Int in return num * 2 } 
  1. filter: 조건에 맞는 원소만 남긴다
let even = numbers.filter { $0 % 2 == 0 } print(even) 
  1. reduce: 모든 원소를 합쳐 하나의 값으로 줄임
let sum = numbers.reduce(0) { $0 + $1 } print(sum) // 15 

3. SwiftUI

사실 SwiftUI는 클로저로 뷰와 동작을 연결하는 프레임워크라고 봐도 무방하다.

  1. Button(action:)
Button("Tap Me") { print("Button tapped!") } 
  1. onTapGesture
Text("Hello") .onTapGesture { print("Text tapped!") } 
  1. List + map
let names = ["James", "Alice", "Bob"] List { ForEach(names, id: \.self) { name in Text("Hello, \(name)") } } 
ForEach(names, id: \.self) { Text("Hello, \($0)") } 

[!note] 잘 이해하다가 [[ForEach]]에서 막혔다. 그래서 공부하고 돌아왔다.

  1. 애니메이션
@State private var isOn = false var body: some View { VStack { Circle() .animation(.easInOut, value: isOn) Button("Toggle") { isOn.toggle } } } 
  1. 비동기 네트워크 예시
func fetchData(completion: @escaping (String) -> Void) { DispatchQueue.global().async { // 서버 통신했다고 가정 let result = "Data from server" DispatchQueue.main.async { completion(result) // 클로저 실행 } } } struct ContentView: View { @State private var text = "Loading..." var body: some View { Text(text) .onAppear { fetchData { result in text = result } } } } 

정리

연습

숫자 배열 [1, 2, 3, 4, 5]를 ForEach로 돌려서 버튼 5개 만들고, 버튼 누르면 눌린 숫자를 print하는 뷰

let nums = [1, 2, 3, 4, 5] ForEach(nums, id = \.self) { num in Button("\(num)") { print(num) } } 
struct ContentView: View { let nums = [1, 2, 3, 4, 5] var body: some View { ForEach(nums, id: \.self) { num in Button("\(num)") { print(num) } } } } 

👉 여기서 연습 더 나아가서, 버튼 누른 숫자를 print 말고 Text로 화면에 표시하는 버전 만들어볼래? (즉, @State 써서 상태 업데이트)

struct ContentView: View { @State var number: Int let nums = [1, 2, 3, 4, 5] var body: some View { ForEach(nums, id: \.self) { num in Button("\(num)") { $number = num } } Text(number) } } 
struct ContentView: View { @State private var number = 0 let nums = [1, 2, 3, 4, 5] var body: some View { ForEach(nums, id: \.self) { num in Button("\(num)") { number = num } } Text("Selected: \(number)") .padding() } } 

연습문제

숫자 배열 [1, 2, 3, 4, 5]가 있어. 이 배열을 map과 클로저를 사용해서 아래처럼 바꿔라:

["1점수", "2점수", "3점수", "4점수", "5점수"]

let nums = [1, 2, 3, 4, 5] let result = nums.map { "\($0)점수" } print(result)