TIL 13일 차 - Swift 문법 과제 최종 리펙토링
과제 풀이 Github 링크
<필수 과제>
1번 문제.

🍏 클로저 본문이 한 줄이면 in return에서 return 생략 가능하다.
let sum: (Int, Int) -> String = { a, b in
return "두 수의 합은 \(a + b) 입니다."
}
let sum: (Int, Int) -> String = { a, b in
"두 수의 합은 \(a + b) 입니다." // return을 생략하더라도 마지막 한 줄이 자동 반환
}
2번 문제.

🍏 .map { String($0) }는 각 요소를 받아서 String(요소)로 바꾸는 것이다.
그런데 String($0)은 String의 생성자를 부르는 것이므로 그 생성자 자체를 map에 바로 넘길 수 있다.
따라서 map(String.init)으로 써도 같은 결과가 출력된다.
let numbers = [1, 2, 3, 4, 5]
let resultA = numbers.map { String($0) }
let resultB = numbers.map(String.init)
print(resultA) // ["1", "2", "3", "4", "5"] 출력
print(resultB) // ["1", "2", "3", "4", "5"] 출력
🍏 또한 짝수값을 출력하기 위해 썼던. filter { $0 % 2 == 0 } 대신 { $0.isMultiple(of: 2) }를 활용하여도 같은 결과가 출력된다.
해당 구문은 $0에 해당하는 값이 2의 배수에 해당하는지를 Bool로 돌려주게 된다.
let numbers2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let resultA = numbers2.filter { $0 % 2 == 0}.map { String($0) }
let resultB = numbers2.filter { $0.isMultiple(of: 2) }.map(String.init)
print(resultA) // ["2", "4", "6", "8", "10"] 출력
print(resultB) // 같은 값 출력
3번 문제.


🍏 기존 풀이 방식인 for문과 if문을 이용해서 풀 수도 있지만
입력받은 array배열을. enumerated()를 이용해 배열을 '인덱스(offset) + 값(element)' 형태인 EnumeratedSequence라는 타입으로 만들어 문제를 보다 간결하게 풀어줄 수 있다.
func a(_ array: [Int]) -> [Int] {
array.enumerated() // [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
.filter { (idx, _) in // 튜플에서 인덱스만 보고 2의 배수인것만 남긴다
idx.isMultiple(of: 2) // [(0, 1), (2, 3), (4, 5)]만 필터링 되어서 남음
}
.map { (_, value) in // 튜플에서 value값만 뽑아서 배열로 만듬
value
}
// [1, 3, 5]
// 위의 구문도 따지고 보면 한줄이라 return 생략함
}
print(a([1, 2, 3, 4, 5])) // [1, 3, 5] 출력
4번 문제.



🍏 나는 프로퍼티 옵서버에서 willSet을 이용하여 풀었는데 didSet을 이용해서도 풀이할 수 있다.
class Robot {
var name: String {
didSet {
guard oldValue != name else {
return // 이전값과 동일하면 return으로 빠져나감
}
let log = """
name 변경 알림
변경 이전 값: \(oldValue)
변경 이후 값: \(name)
"""
print(log)
}
}
init(name: String) {
self.name = name
}
}
var robot = Robot(name: "로봇1")
robot.name = "로봇2" // name 변경 알림 변경 이전 값: 로봇1 변경 이후 값: 로봇2 출력
1) didSet
- 바뀐 다음에 실행함
- oldValue(이전 값)을 쓸 수 있음
- 이 시점의 name은 이미 새로 대입한 값임
2) willSet
- 바뀌기 전에 실행
- newValue(바뀔 값)을 쓸 수 있음
- 이 시점의 name은 아직 기존에 있던 값
🍏 for 반복문안에서 if문을 쭉 나열하면 앞에서 검사가 통과해도 뒤에 나열된 if문을 또 실행하게 되어 불필요한 실행이 반복된다.
// 반복문을 비효율적으로 작성한 코드 (수정 전 기존 코드)
for i in arrayIntroducible {
if let robot = i as? Robot {
print(robot.batteryCharge()) // 전원을 충전합니다. 출력
}
if let cat = i as? Cat {
print(cat.grooming()) // 야옹 출력
}
if let dog = i as? Dog {
print(dog.bark()) // 멍멍멍 출력
}
}
// 3 x 3 = 총 9번 타입 검사를 반복함
🍏 else if 문을 이용해 비효율적인 반복을 줄이고 가독성을 높일 수 있다.
🍏 배열은 선언과 동시에 초기화를 해주면 더 간결하게 코드를 작성할 수 있다.
🍏 for in 문 대신 forEach(단, break 불가) 문을 이용할 수도 있다. (for-in 도 괜찮은 선택임)
let introducibles: [Introducible] = [robot, cat, dog] // 선언과 동시에 초기화
// 또한 앞으로 변경될 일 없는 배열 introducible는 var 대신 let으로 선언하는게 좋다.
arrayIntroducible.forEach { // for-in문을 forEach문으로 변경
// i.batteryCharge() error: Value of type 'any Introducible' has no member 'batteryCharge'
if let robot = $0 as? Robot { // 비효율적인 반복을 줄이고 가독성 향상을 위해 else if문으로 수정
print(robot.batteryCharge())
} else if let cat = $0 as? Cat {
print(cat.grooming())
} else if let dog = $0 as? Dog {
print(dog.bark())
}
}
// 3! = 총 6번 반복문을 실행하게 된다.
5번 문제.

🍏 throwing function을 정의할 때 if - else문을 사용할 수도 있지만 해당 조건에서는
guard문을 사용하면 조건 실패 시 바로 종료이기 때문에, if문을 사용했을 때 발생했던 else로 감싸서 발생한 들여 쓰기(중첩)이 사라져 가독성이 나아진다.
func predictDeliveryDay(for address: String, status: DeliveryStatus) throws -> String {
guard !address.isEmpty else {
throw DeliveryError.invalidAddress
}
// if else 대신 guard문 사용으로 가독성에 방해되는 들여쓰기 삭제 됨

해. 보. 자(코딩 감금 쏘우방) 탈출 완료!
'iOS > Swift ' 카테고리의 다른 글
| [iOS-Swift] 객체 지향 프로그래밍 OOP (0) | 2026.01.14 |
|---|---|
| [iOS-Swift] 스위프트에서 사용자 입력받기 (0) | 2026.01.13 |
| [iOS-Swift] ARC (1) | 2026.01.12 |
| [iOS-Swift] 클로저 closure 심화 (0) | 2026.01.12 |
| [iOS- Swift] 스위프트 필수 문법 문제 5번 풀이 (0) | 2026.01.10 |