- swift에 대해 공부한 내용을 정리한 글입니다.
- 해당 글은 한빛미디어의 스위프트 프로그래밍 3판을 참고하여 작성했습니다.
프로그램을 작성하다보면 특정 조건에서 코드를 실행해야 하거나, 특정 명령어를 반복해야하는 일이 종종 발생한다. 이럴 때 사용하는 것이 바로 조건문과 반복문이다.
대부분의 프로그래밍 언어에서 조건문과 반복문을 다루지만 스위프트는 다른 언어와 차이가 있으니 유의해야 한다. 스위프트의 흐름 제어 구문에서는 소괄호()를 대부분 생략할 수 있으나, 중괄호{}는 생략할 수 없다.
따라서 이번에는 조건문과 반복문에 대해 공부하고자 한다.
조건문으로는 if 구문과 swift 구문이 있다. 스위프트에는 guard 구문도 있으나, 이는 추후에 다루고자 한다.
if 구문은 대표적인 조건문으로 if, else 등의 키워드를 사용하여 구현할 수 있다. 정수, 실수 등 0이 아닌 모든 값을 참으로 취급하여 조건 값이 될 수 있었던 다른 언어와는 달리 스위프트의 if 문은 조건의 값이 꼭 Bool 타입 이어야 한다.
if 구문의 기본적인 사용은 다음과 같다.
if 조건 수식1 {
실행 코드
}
else if 조건 수식2 {
실행 코드
}
else if 조건 수식3 {
실행 코드
}
else {
실행 코드
}
else if는 몇 개가 이어져도 상관 없으며 else 블록은 없어도 상관이 없다.
if 문에서 여러 개의 조건을 순차적으로 대조하다가 특정 조건에 일치한다면 그에 해당하는 코드를 실행하고, 그 다음에 이어진 조건문은 조건에 충족하더라도 실행되지 않고 조건문을 빠져나온다.
이때 각 블록의 조건에는 소괄호()를 붙이지 않아도 상관이 없다.
다음은 if 구문을 사용해 두 변수의 값을 비교하는 코드이다.
let first: Int = 1
let second: Int = 2
if first > second {
print("first > second")
} else if first < second {
print("first < second")
} else {
print("first == second")
}
first > second
기본 문법이라 할 수 있는 switch 구문은 다른 언어와 비교했을 때 많이 달라진 문법 중 하나이다. switch 구문도 if문 처럼 소괄호()를 생략할 수 있으며, break 키워드 또한 선택적으로 사용한다.
즉, case 내부의 코드를 실행하면 break 없이도 switch 구문이 종료된다는 뜻인데, 이 방식은 예상치 못한 실수를 중이는 데도 큰 도움이 된다.
C 언어에서는 조건에 정수 타입만 들어갈 수 있었지만, 스위프트에서는 다양한 값이 들어갈 수 있다. 다만 각 case에 들어갈 비교 값은 입력 값과 데이터 타입이 같아야 한다.
또, 비교될 값이 명확히 한정적인 값(열거형 값 등)이 아닐 때는 default를 꼭 작성해야 한다.
각 case에는 범위 연산자나 where 절을 사용해 조건을 확장할 수 있다.
swift 입력 값 {
case 비교 값1 :
살행 코드
case 비교 값2 :
실행 코드
// 이번 case를 마치고 switch 구문을 탈출하지 않음
fallthrough
case 비교 값3, 비교 값4, 비교 값5 : // 한 번에 여러 값 비교 가능
실행 코드
break // break 키워드의 사용은 선택 사항
default :
실행 코드
}
let integerValue: Int = 5
switch integerValue {
case 0:
print("Value == Zero")
case 1...10:
print("Value == 1~10")
fallthrough
case Int.min..<0, 101..<Int.max:
print("Value < 0 or Value > 100")
break
default:
print("10 < Value <= 100")
}
Value == 1~10
Value < 0 or Value > 100
위의 코드처럼 case의 비교 값에 단 하나의 값 뿐만이 아니라 범위 연산자를 넣을 수도 있다.
결과에서 "Value < 0 or Value > 100"이 출력된 이유는, 두 번째 블록에서 fallthrough 키워드를 사용하여 세 번째 블록도 실행되도록 했기 때문이다.
만약 integerValue의 값이 0이었다면, "Value == zero"만 출력됐을 것이다.
범위 연산자는 정수 뿐만이 아니라 부동소수 타입에도 사용할 수 있으며, switch 구문의 입력 값으로는 숫자 뿐만이 아니라 문자, 문자열, 열거형, 튜플 등의 타입 값도 사용할 수 있다.
int num = 3;
switch (num) {
case 0:
case 1:
case 2:
case 3:
print("num >= 3");
default:
print("num < 3")
}
위 코드는 java를 사용해 작성한 switch 코드이다. java나 C 등은 처럼 case 안의 실행 코드를 생략하며 사용할 수 있지만, 스위프트에서 이러한 방식을 사용하게 되면 오류가 발생한다.
따라서 위와 같은 코드를 작성하고 싶을 때는 fallthrough 키워드를 사용해야 한다.
let num: Int = 3
switch num {
case 0:
fallthrough
case 1:
fallthrough
case 2:
fallthrough
case 3:
print("num >= 3")
default:
print("num < 4")
}
조건에 따라 실행되어야 하는 명령어를 조건문을 통해 분기하거나, 같거나 비슷한 명령을 반복할 때 반복문을 사용할 수 있다. 특히나 배열과 같은 시퀀스, 순서가 있는 데이터는 반복문으로 더욱 편리하게 처리할 수 있다.
스위프트의 반복문은 기존 프로그래밍 언어의 반복문과 크게 다르지 않다. 전통적인 C 스타일의 for 구문이 사라졌다는 점과 조건에 소괄호()를 생략할 수 있다는 점을 제외하고 말이다.
또한 do-while 구문은 스위프트에서 repeat-while 구문으로 구현되어 있다.
for-in 반복 구문은 반복적인 데이터나 시퀀스를 다룰 때 많이 사용한다. 다른 언어에서의 for-each 구문과 유사하다.
for 루프 상수 in 시퀸스 아이템 {
실행 코드
}
for i in 0...2 {
print(i)
}
0
1
2
for i in 0...5 {
if i.isMultiple(of: 2) {
print(i)
continue // continue 키워드를 사용하면 바로 다음 시퀸스로
}
print("\(i) == 홀수")
}
0
1 == 홀수
2
3 == 홀수
4
5 == 홀수
let helloSwift: String = "Hello Swift!"
for char in helloSwift {
print(char)
}
H
e
l
l
o
S
w
i
f
t
!
var result: Int = 1
// 시퀀스에 해당하는 값이 필요 없다면 와일드카드 식별자(_)를 사용
for _ in 1...3 {
result *= 10
}
print("10의 3제곱은 \(result) 입니다.")
10의 3제곱은 1000 입니다.
// Dictionary
let friends: [String: Int] = ["Kim": 20, "Lee": 22, "Park": 21]
for tuple in friends {
print(tuple)
}
(key: "Kim", value: 20)
(key: "Park", value: 21)
(key: "Lee", value: 22)
let address: [String: String] = ["도": "경기도", "시군구": "성남시 성남구", "동읍면": "성남동"]
for (key, value) in address {
print("\(key) : \(value)")
}
동읍면 : 성남동
도 : 경기도
시군구 : 성남시 성남구
// Set
let areaCode: Set<String> = ["02", "031", "032", "033", "041", "042"]
for code in areaCode {
print(code)
}
041
042
033
02
031
032
for-in 구문을 사용하여 반복 처리를 쉽게 할 수 있다.
하지만 스위프트에 더 익숙해지면 for-in 구문보다 map, filter, flatMap등을 더 많이 사용하게 될 것이다.
while 반복 구문도 다른 프로그래밍 언어의 while 구문과 크게 다르지 않는다. 특정 조건(Bool 타입으로 지정되어야 한다.)이 성립하는 한 블록 내부의 코드를 반복해서 실행한다.
for-in 구문과 마찬가지로 continue, break 등의 키워드를 사용할 수 있다.
var names: [String] = ["Kim", "Lee", "Park"]
while !names.isEmpty {
print("Good bye \(names.removeFirst())")
}
Good bye Kim
Good bye Lee
Good bye Park
repeat-while 반복 구문은 다른 프로그래밍 언어의 do-while 구문과 크게 다르지 않다. repeat 블록의 코드를 먼저 실행한 후, while 다음의 조건이 성립하면 블록 내부의 코드를 반복 실행한다.
var names: [String] = ["Kim", "Lee", "Park"]
repeat {
print("Good bye \(names.removeFirst())")
} while names.isEmpty == false
Good bye Kim
Good bye Lee
Good bye Park
반복문을 작성하다 보면 종종 반복문을 중첩으로 작성하게 된다.
이때 반복문을 제어하는 키워드가 어떤 범위에 적용되어야 하는 지 애매하거나 큰 범위의 반복문을 종료하고 싶은데 작은 범위의 반복문만 종료되는 등 예상치 못한 실수를 할 수도 있다.
이러한 경우에는 반복문 앞에 이름과 함께 콜론을 붙여 구문의 이름을 지정해주면 좋다.이름이 지정된 구문을 제어하고자 할 때는 제어 키워드와 구문 이름을 함께 써주면 된다.
var numbers: [Int] = [3, 2342, 6, 3252]
numbersLoop: for num in numbers {
if num > 5 || num < 1 {
continue numbersLoop
}
var count: Int = 0
printLoop: while true {
print(num)
count += 1
if count == num {
break printLoop
}
}
removeLoop : while true {
if numbers.first != num {
break numbersLoop
}
numbers.removeFirst()
}
}
print(numbers)
3
3
3
[2342, 6, 3252]