
자세히 공부한 주제에만 맞게 TIL을 쓰려고 했는데 배우는 입장에서 내가 그 중요도를 판단 할 수 있다는 거 자체가 어불성설 같다.
일단 조금이나 배우거나 공부한 걸 조금 내용이 부족하더라도 다 정리해 보고자 한다. 이렇게 하는게 나중에 더 자세히 공부할 때 도움이 될 것 같다.
whereclause is used to specify additional constraints or conditions
(Swift Language Guide – Generics, Control Flow)
where는 코드가 동작하기 위해서는 이런 조건을 만족해야 한다고 추가 조건을 명시하는 코드이다.
if: 실행흐름을 제어
where: 문법적 제약 / 조건필터 역할을 한다. 이 문법이 성립할 수 있는 조건을 명시한다.
let numbers = [1, 2, 3, 4, 5]
//where사용
for number in numbers where number % 2 == 0 {
print(number)
}
//if 사용
for number in numbers {
if number % 2 == 0 {
print(number)
}
}
기능은 같지만 짝수만 순회한다라는 필터링 의도가 명확해진다.
switch + where스위치 문과 조건 분기를 나눌때
let score = 85
switch score {
case let x where x >= 90:
print("A")
case let x where x >= 80:
print("B")
default:
print("C")
}
catch + where같은 에러지만 이런식으로 조건에 따라 다르게 처리 할 수 있다.
enum NetworkError: Error {
case serverError(code: Int)
}
do {
throw NetworkError.serverError(code: 500)
} catch NetworkError.serverError(let code) where code >= 500 {
print("서버 오류")
}
Generic+ wherewhere로 조건을 명확하게 할 수 있다.
Comparable을 만족할때만 sortItems함수를 쓸 수 있다.
struct SortableBox<T> {
var items: [T]
mutating func sortItems() where T: Comparable {
items.sort()
}
}
제네릭 타입간의 관계를 나타내는데도 용이하다.
func compare<T, U>(a: T, b: U)
where T: Equatable, U: Equatable, T == U {
print(a == b)
}
extension + whereextension를 활용해 의도한데로 기능을 부여할 수 있다.
아래의 extension은 Int배열 일때만 존재할 수 있다.
extension Array where Element == Int {
func sum() -> Int {
reduce(0, +)
}
}
[1, 2, 3].sum() // 가능
["a", "b"].sum() // ❌ 컴파일 에러
고차함수란 “함수를 인자로 받거나, 함수를 반환하는 함수”
map - 값을 변환하는 고차함수nil을 제거하지 않음let numbers = [1, 2, 3, 4, 5]
let result = numbers.map { number in
return number * 2
}
func map<T>(_ transform: (Element) -> T) -> [T]
compactMap - nil 제거 후 압축 반환nil을 제거하는 map Optional 제거, 실패 가능한 변환, JSON 파싱 후 데이터 정리let values = [1, nil, 3]
let result = values.compactMap { $0 }
// [1, 3]
let strings = ["1", "2", "a", "3"]
let numbers = strings.compactMap { Int($0) }
// [1, 2, 3] 변환시 nil이 된 것들이 제거됨
flatMap - 중첩된 컬렉션을 한 단계 펼쳐주는 함수let nested = [[1, 2], [3, 4]]
let flat = nested.flatMap { $0 }
// [1, 2, 3, 4]
forEach- 각 요소에 대해 작업만 수행하는 함수for-in 선택)let numbers = [1, 2, 3]
numbers.forEach {
print($0)
}
filter - 조건으로 걸러내는 고차함수filter안의 클로저는 bool값의 결과에 따라서 true일 경우 남기고 false는 버린다.let numbers = [1, 2, 3, 4, 5]
let evenNumbers = numbers.filter { $0 % 2 == 0 }
//[2, 4]
func filter(_ isIncluded: (Self.Element) throws -> Bool) rethrows -> [Self.Element]
reduce- 하나의 값으로 합치는 고차함수let numbers = [1, 2, 3, 4]
let sum = numbers.reduce(0) { result, number in
result + number
}
// 10
func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
initialResult: 초기값으로 사용할 값을 넣으면 클로저가 처음 실행될 때 nextPartialResult에 전달됨nextPartialResult: 컨테이너의 요소를 새로운 누적값으로 결합하는 클로저{ [캡처 리스트] (매개변수) -> 반환값 in
실행 코드
}
{ [weak self] in
self?.doSomething()
}
var count = 0
let closure = { [count] in
print(count)
}
count 값이 복사됨count값이 변경 되어도 영향이 없다class Box {
var value = 0
}
let box = Box()
let closure = { [box] in
print(box.value)
}
box 참조를 캡처함, 값이 반영됨strong, weak, unowned 중에 어떤 방식으로 잡을 것인가 인지를 제어weakescaping 클로저일 때(나중에 실행 될 수 있을때) self를 약한 참조로 캡처self가 사라지면 -> nil{ [weak self] in
self?.doSomething()
}
api.request { [weak self] result in
guard let self else { return }
self.updateUI(result)
}
weak self + guard let self 함께 사용unowned{ [unowned self] in
self.doSomething()
}
nil 체크 없음self가 이미 해제된 경우라면 크래시self 살아있음이 보장되며 성능상 유리할 때 권장enum DeliveryError: Error {
case invalidAddress
case notStarted
case systemError(reason: String)
}
catch let error {
print(error)
}
위의 코드는 어떤 종류의 에러든 일단 Error로 받는 범용 핸들러
throw → Error 프로토콜 타입으로 포장 → catch로 전달
throw DeliveryError.invalidAddress를 던지면 실제로는 Error 타입으로 업캐스팅되어서 catch로 전달된다.
이게 가능한 이유는 swift가 자동으로 문자열로 만들어주는 CustomStringConvertible 구현을 제공하기 때문임
print(error)는 사실상 print(String(describing: error)) 호출하는것과 같다. 결과적으로는 "DeliveryError.systemError(reason: "DB down")" 이런 식으로 print되는 걸 볼 수 있음.
에러 별로 나누고 싶다면 이런식으로 쓸 수 있다.
// 상수 활용
catch let error as DeliveryError {
print("배송 에러:", error)
}
catch {
print("기타 에러:", error)
}
//enum값 활용
catch DeliveryError.invalidAddress {
print("주소 잘못됨")
}
catch DeliveryError.systemError(let reason) {
print("시스템 에러:", reason)
}