티스토리 뷰
원문 : https://www.hackingwithswift.com/swift/5.9/if-switch-expressions
기능
매개변수 팩으로 다양한 타입을 묶어 사용하기
struct FrontEndDev {
var name: String
}
struct BackEndDev {
var name: String
}
struct FullStackDev {
var name: String
}
위와 같은 구조체 3개가 있다고 가정해보자.
let johnny = FrontEndDev(name: "Johnny Appleseed")
let jess = FrontEndDev(name: "Jessica Appleseed")
let kate = BackEndDev(name: "Kate Bell")
let kevin = BackEndDev(name: "Kevin Bell")
let derek = FullStackDev(name: "Derek Derekson")
그럼 이런식으로 인스턴스 생성을 했고, 이들을 적절한 팀에 배치하고 싶다.
하나의 함수로 처리한다면 이렇게 할 수 있을 것이다.
func pariUp1<T, U>(firstPeople: T..., secondPeople: U...) -> ([(T, U)]) {
assert(firstPeople.count == secondPeople.count, "페어링할 사람 수를 동일하게 제공해야 합니다.")
var result = [(T,U)]()
for i in 0..<firstPeople.count {
result.append((firstPeople[i], secondPeople[i]))
}
return result
}
이 함수로 백엔드 2, 프론트엔드 2 이렇게 짝을 지을 수 있다.
let result1 = pairUp1(firstPeople: johnny, jess, secondPeople: kate, kevin)
그런데 앞서 작성한 코드를 보면 derek 이라는 개발자는 풀스택이기 때문에 firstPeople, secondPeople 둘 다 사용할 수 있다. 하지만 프론트엔드 개발자와 풀스택 개발자는 타입이 다르기 때문에 매개변수에 동시에 사용할 수 없다는 것이 문제다.
그럼 어떻게 해야할까? Any
를 사용할 수 있지만 이번엔 매개변수 팩을 이용해서 우아하게 해결해보자.
func pairUp2<each T, each U>(firstProple: repeat each T, secondPeople: repeat each U) -> (repeat (first: each T, second each U)) {
return (repeat (each firstPeople, each secondPeople))
}
이 함수는 4가지의 독립적인 일이 일어나고 있다.
<each T, each U>
는 두 개의 유형 매개변수 팩T
와U
를 생성한다.repeat each T
는 팩 확장(pack expansion)으로, 매개변수 팩(parameter pack)을 실제 값으로 확장한다.T...
와 동일하지만 연산자로 사용되는...
와의 혼동을 피할 수 있다.- 반환 타입은
T
와U
에서 각각 하나씩 짝을 이룬 프로그래머 튜플을 반환한다는 뜻이다. - 반환 키워드는 실제 작업을 수행하는 것으로, 팩 확장 표현식(pack expansion expression)을 사용하여
T
에서 하나의 값과U
에서 하나의 값을 가져와 반환된 값으로 합친다.
each
키워드를 작성하지 않으면 반환 유형이 자동으로 T
유형과 U
유형의 모양이 동일하고 그 안에 같은 수의 항목이 있는지 확인한다는 것이다. 따라서 첫 번째 함수에서처럼 assert()
를 사용하지 않고 크기가 다른 두 개의 데이터 세트를 전달하려고 하면 컴파일러 오류를 발생시킨다.
이 함수를 이용하면 이제 다음과 같이 데릭을 다른 개발자와 짝을 이룰 수 있다.
let result2 = pairUp2(firstPeople: johnny, derek, secondPeople: kate, kevin)
우리가 작성한 것은 간단한 zip()
함수를 작성한 것이므로 아래처럼 말도안되는 코드도 작성할 수 있다.
let result3 = pairUp2(firstPeople: johnny, derek, secondPeople: kate, 556)
일반적인 zip()이라면 케빈과 556를 연결하기 쉽지 않다. 이 지점에서 매개변수 팩의 진가가 발휘되는데, 이는 아래와 같은 프로토콜을 정의할 수 있기 때문이다.
protocol WritesFrontEndCode { }
protocol WritesBackEndCode { }
그런 다음 몇 가지 적합성을 추가한다.
FrontEndDev
는WritesFrontEndCode
를 준수해야 한다.BackEndDev
는WritesBackEndCode
를 준수해야 한다.FullStackDev
는WritesFrontEndCode
와WritesBackEndCode
를 모두 준수해야 한다.
이제 유형 매개변수 팩에 제약 조건을 추가할 수 있다.
func pairUp3<each T: WritesFrontEndCode, each U: WritesBackEndCode>(firstPeople: repeat each T, secondPeople: repeat each U) -> (repeat (first: each T, second: each U)) {
return (repeat (each firstPeople, each secondPeople))
}
이제 풀스택 개발자인지 여부에 관계없이 프론트엔드 코드를 작성할 수 있는 사람과 백엔드 코드를 작성할 수 있는 사람이 항상 짝을 이룰 수 있는 합리적인 조합만 가능하다.
SwiftUI
에서도 비슷한 상황이 발생한다. 우리는 텍스트 뷰, 이미지 뷰 등을 조합하여 뷰를 생성하고 또 하위뷰들을 생성하기 원한다. 이때 AnyView...
등을 사용하여 유형을 지우려고 하면 모든 유형 정보가 버려지므로 Swift 5.9 이전에는 많은 함수 오버로드를 생성하여 이 문제를 해결했다.
예를 들어 SwiftUI
의 ViewBuilder
에는 최대 10개의 뷰를 결합할 수 있는 buildBlock()
오버로드가 있지만 어딘가에 선을 그려야 하므로 그 이상은 불가능하다.
'Apple > Swift' 카테고리의 다른 글
[Swift 5.9] Noncopyable structs and enums (0) | 2024.01.11 |
---|---|
[Swift 5.9] Macro (0) | 2024.01.11 |
[Swift 5.9] if and switch expressions (1) | 2024.01.08 |
[Swift Basic] `@unknown` 키워드는 언제 쓰면 좋을까? (0) | 2024.01.05 |
Swift의 집합 개념과 연산 (0) | 2022.09.12 |
- Total
- Today
- Yesterday
- 자바
- CellStyle
- 이코테
- 의존성
- 꼼꼼한 재은 씨의 스위프트 문법편
- it seminar
- SWIFT
- swift5.9
- Swift Conference
- 싱글톤
- UITableViewCell
- ios
- AsyncSwift Korea Seminar
- 핵심내용
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |