흐름 제어 구문
코드의 활용성을 높여 주는 흐름 제어 구문
반복문
주어진 조건에 의해 특정 조건을 반복적으로 실행할 수 있게 해주는 구문
🚀 Loop : 프로그래밍에서 코드 블록의 반복
🚀 스위프트에서 제공하는 반복문은 루프 횟수가 정해져 있는지를 기준으로 두 가지 방식으로 나눌 수 있다. → for 반복문
, while문
for ~ in 구문
for <루프 상수> in <순회 대상> {
<실행할 구문>
}
- 위의 구문을 실행하기 위해서 세가지 항목이 필요하다.
→
루프 상수
,순회 대상
,실행할 구문
- 순회 대상으로 사용할 수 있는 데이터 타입
→
배열
,딕셔너리
,집합
,범위 데이터
,문자열(String)
// 구구단 2단 출력하기
for row in 1...9 {
print("2 X \(row) = \(row * 2)")
}
- 루프 상수는 루프 안에서만 사용할 수 있다.
// 문자열의 문자 순회
var lang = "swift"
for char in lang.characters {
print("개별 문자는 \(char) 입니다.")
|
// 실행 결과
개별 문자는 s 입니다.
개별 문자는 w 입니다.
개별 문자는 i 입니다.
개별 문자는 f 입니다.
개별 문자는 t 입니다.
🚀 루프 상수의 생략
for ~ in 구문을 사용할 때 루프 상수가 필요하지 않을 수도 있다. 순회 대상 자체보다는 단순히 순회 대상의 크기만큼 반복하는 것이 목적인 경우이다. 이때에는 언더바(_)를 사용하여 루프 상수를 생략할 수 있다.
// 사이즈 만큼 keyword 문자열의 왼쪽에 0을 채워 넣기
let size = 5
let padChar = "0"
let keyword = "3"
for _ in 1...size {
keyword = padChar + keyword
}
print("\(keyword)")
// 실행 결과
000003
🚀 for ~ in 구문의 중첩
여러개의 for ~ in 문이 중첩된 형태를 다중 루프 라고 부른다. 다중 루프를 효과적으로 사용하면 굉장한 시너지 효과를 발생시키지만 코드의 해석을 난해하게 하는 주범이 되기도 하므로 주의해야 한다.
// 구구단 1단부터 9단 출력하기
for i in 1..<10 {
for j in i..<10 {
print("\(i) X \(j) = \(i * j)")
}
}
while 구문
🚀 for ~ in 구문은 미리 정의된 횟수만큼만 반복하지만 while 구문은 단순히 주어진 조건식의 결과가 false가 될 때까지 실행 구문을 계속 반복 수행한다. 다시 말해서 while 구문은 ' 조건을 만족하는 동안은 계속 실행 ' 되는 것으로 이해하면 된다.
🚀 while 구문을 사용해야 하는 경우는 아래와 같다.
- 실행 횟수가 명확하지 않을 때
- 직접 실행해보기 전까지는 실행 횟수를 결코 알 수 없을 때
- 실행 횟수를 기반으로 할 수 없는 조건일 때
whlie <조건식> {
<실행할 구문>
}
// 예시
var n = 2
while n < 1000 {
n = n * 2
}
print("n = \(n)")
// 실행 결과
n = 1024
repeat ~ while 구문
🚀 repeat~while 구문은 다른 언어에서 do ~ while 구문에 해당하는 것이다.
🚀 repeat~while 구문은 실행 블록의 수행을 최소 한번은 보장한다는 특성을 가진다.
repeat {
<실행할 구문>
}
while <조건식>
조건문
if 구문
🚀 하나 또는 그 이상의 조건을 평가하고 결과에 따라 코드 블록의 실행 여부를 결정하는 구문
🚀 조건문은 반드시 Bool 타입의 참, 거짓을 판단할 수 있는 형태의 구문이어야 한다.
if <조건식> {
<실행할 구문>
}
var adult = 19
var age = 15
if age < adult {
print("미성년자!")
}
if ~ else
🚀 조건식이 참일 때는 A 구문을, 거짓일 때는 B 구문을 실행하고 싶을 때
var adult = 19
var age = 15
if age < adult {
print("미성년자!")
} else {
print("성년자!")
}
🚀 if 구문의 중첩
var adult = 19
var age = 21
var gender = "M"
if adult > age {
if gender == "M" {
print("남자 미성년자")
} else {
print("여자 미성년자")
}
} else {
if gender == "M" {
print("남자 성년자")
} else {
print("여자 성년자")
}
}
🚀 if ~ else if : 비교할 조건이 여러개일 경우
if gender == "M" {
print("남자 미성년자")
} else if gender == "F" {
print("여자 미성년자")
} else {
print("남자도 여자도 아니다.")
}
🚀 컴파일러는 if ~ else if ~ 구문으로 작성된 구문은 하나의 조건식으로, if ~ if ~ 구문으로 작성된 구문은 서로 별개의 조건문으로 인식한다. 따라서 if ~ else if 구문에서는 차례대로 조건식을 비교하다가 일치하는 것이 발견되면 더이상 비교를 진행하지 않고 조건문을 종료하지만, 이것을 if ~ if ~ 문으로 작성하면 이미 일치하는 조건식이 발견되었더라도 끝까지 모든 조건식을 비교한다. 컴퓨터 입장에서는 불필요한 리소스가 낭비되므로 지양하는 것이 좋다.
guard 구문
🚀 guard 구문은 if 구문과 마찬가지로 주어진 표현식의 결과가 참인지 거짓인지에 따라 구문의 실행 여부를 결정짓는 방식의 조건문이다. if 구문과의 차이점은
guard 구문에는 else 블록이 필수이지만, 표현식의 결과가 참일 떄 실행되는 블록이 없다는 점이다.
guard <조건식 또는 표현식> else {
<조건식 또는 표현식의 결과가 false일 때 실행될 코드>
}
🚀 guard 구문은 주로 후속 코드들이 실행되기 전에 특정 조건을 만족하는지 확인하는 용도로 사용된다. 다시 말해 특정 조건을 만족하지 않은 채로 후속 코드를 실행하면 심각한 오류가 발생할 경우에, 전체 구문을 조기 종료하기 위한 목적으로 사용되는 것이 guard 구문이다.
func divide(base: Int) {
guard base != 0 else {
print("연산 불가")
return
}
let result = 100 / base
print(result)
}
위의 코드를 if 문으로 작성하면
func divide(base: Int) {
if base == 0 {
print("연산 불가")
return
}
let result = 100 / base
print(result)
}
🚀 guard 구문은 언뜻 보기에 if문으로 대체가 가능하기 때문에 그다지 필요없어 보일 수도 있다. 하지만 guard 구문은 본래 실행 흐름을 종료하기 위한 목적으로 사용되는 구문이기 때문에, 코드를 중첩해서 사용하지 않아도 된다는 장점이 있다.
func divide(base: Int) {
guard base != 0 else {
print("연산 불가")
return
}
guard base > 0 else {
print("base는 0보다 커야한다.")
return
}
guard base < 100 else {
print("base는 100보다 작아야 한다.")
return
}
let result = (100 / base)
print(result)
}
🚀 이런 특성 때문에 조건을 체크하여 실행 흐름을 종료시킬 때에는 가급적 guard 구문을 사용하는 것이 좋다. 조건을 체크하되 다른 실행 흐름을 이어나가고 싶은 경우에만 if ~ else 구문을 사용하면 된다.
#available 구문
🚀 앱을 개발하다 보면 기기의 OS 버전별로 구문을 나누어 작성해야 할 때가 종종 있다. 이럴 때 #available 구문을 사용한다.
if #available( <플랫폼 이름 버전>, <...>, <*> ) {
< 해당 버전에서 사용할 수 있는 API 구문 >
} else {
< API를 사용할 수 없는 환경에 대한 처리 >
}
- #available 구문을 사용할만한 플랫폼은 현재 네 가지가 거의 전부이다.
→ 아이폰, 아이패드 등 터치 기반 스마트 기기에 사용되는 iOS
→ 맥 컴퓨터에 사용되는 OSX
→ 애플 시게에 사용되는 watchOS
→ 애플 TV에 사용되는 tvOS
switch 구문
🚀 switch 문은 if문과 guard 문처럼 분기문의 일종이지만, 처리 방식은 앞에서와 다르다. switch 구문은 입력받은 값을 조건식 여부가 아니라 패턴으로 비교하고 그 결과를 바탕으로 실행 블록을 결정하는 조건문이다. 이 구문은 나열된 패턴들을 순서대로 비교하다가 일치하는 첫 번째 패턴의 코드 블록을 실행하고 더이상의 비교 없이 분기문을 종료한다. 따라서 break문도 필요 없다.
switch <비교 대상> {
case <비교 패턴1> :
<비교 패턴1이 일치했을 때 실행할 구문>
case <비교 패턴2> :
<비교 패턴2이 일치했을 때 실행할 구문>
default :
<어느 비교 패턴과도 일치하지 않았을 때 실행할 구문>
}
🚀 암시적인 Fall Through → 실행 흐름이 전달된 비교 블록은 패턴 일치 여부에 상관 없이 실행 블록을 처리한다. 그러나 Swift에서는 암시적인 Fall Through를 지원하지 않는다. 물론 case 블록이 비어있어서도 안된다. 대신 명시적으로 fallthrough 구문을 사용함으로써 같은 결과를 얻을 수 있다.
let sampleChar : Character = "a"
switch sampleChar {
case "a":
fallthrough
case "A":
print("글자는 A 입니다.")
default :
print("일치하는 글자가 없습니다.")
}
// 실행 결과
글자는 A 입니다.
🚀 switch 구문의 특성
- 모든 케이스 구문에서 일치된 패턴을 찾지 못했을 경우에 대비하여 switch 구문에는 반드시 default 구문을 추가해야 하며, 만약 default를 생략하면 완전하지 않은 구문으로 간주하여 오류가 발생한다. 단, default 구문을 대신하여 모든 패턴을 매칭시킬 수 있는 구문이 존재하는 경우에 한하여 default 구문을 생략할 수 있다.
- case 비교 패턴을 작성할 때 하나의 case 키워드 다음에 하나 이상의 비교 패턴을 연이어 작성할 수 있다. 두 가지 이상의 패턴에 대해 같은 구문을 실행해야 한다면, 하나의 케이스 키워드로 비교 패턴을 묶어 표현하면 된다. → 키 입력 낭비를 줄이고, 코드를 보다 간결하게 만드는데 효과적이다.
var value = 3 switch value { case 0, 1 : print("0, 1") case 2, 3 : print("2, 3") default : print("default") }
- 케이스 구문에서 사용되는 비교 패턴으로 튜플이나 특정타입으로 캐스팅된 객체도 사용 가능하다.
- 특정 값의 일치 여부를 단순 비교하는 방식 외에 범위 연산자를 이용하여 해당 범위에 속하는 값을 매칭할 수도 있다.
var value = (2, 3) switch value { case (0..<2, 3) : print("범위 A에 포함") case (2..<5, 0..3) : print("범위 B에 포함") default : print("범위 C에 포함") }
- where 구문을 추가하면 각 case 블록 별로 보다 복잡한 패턴까지 매칭이 가능하다.
var value = (2, 3) switch value { case let (x, y) where x == y : print("x와 y는 x==y 선 상에 있다.") case let (x, y) where x == -y : print("x와 y는 x==-y 선 상에 있다.") default : print("x와 y는 일반 좌표상에 있다.") }
제어 전달문
break
switch 구문에서의 실행 흐름이나 반복 실행 중인 루프를 조건식의 결과에 상관 없이 즉각적으로 종료하는 데에 사용된다. 반복문에서는 반복 실행 블록에 사용되어 조건식이 false를 반환하기 전에 미리 반복문을 종료하는 역할을 한다. 반복문 내에서 break 구문을 사용할 경우 이 구문은 반복문의 전체 실행을 즉시 종료하고 반복문의 마지막에 위치한 닫는 중괄호 다음의 첫 번째 코드 줄로 실행 흐름을 전달한다.
continue
continue 구문은 이 구문 아래에 있는 실행 구문들을 건너 뛰고 다음 반복을 시작하는 역할을 한다. continue 구문 아래에 있는 나머지 구문들을 실행하지 않을 뿐, 전체 반복은 계속 유지되는 것이 break 문과의 결정적 차이라고 할 수 있다.