Switch
switch
구문도 소괄호(()
)를 생략할 수 있습니다. 단, break
키워드 사용은 선택 사항입니다. 즉, case
내부의 코드를 모두 실행하면 break
없이도 switch
구문이 종료된다는 의미입니다. 이것은 예상치 못한 실수를 줄이는 데도 큰 도움이 됩니다. 따라서 break
를 사용하지 않고 case
를 연속 실행하던 트릭을 더 이상 하용하지 못합니다. 그렇기 때문에 swift에서 switch
구문의 case
를 연속 실행하려면 fallthrough
키워드를 사용해야 합니다.
Switch 구문의 기본 형태
switch 비교값 {
case 패턴:
/*실행구문*/
default: //else if 같은 개념
/*실행구문*/
}
switch
문을 잘 사용하면if
문 보다 읽기가 훨씬 쉽습니다.- 매우 한정적인 값 (
enum
,case
등)이 비교 값이 아닌 한default
구문은 반드시 작성해야 합니다. case
에break
를 추가하지 않아도 자동으로case
마다break
됩니다.fallthrough
키워드를 사용하여break
되는 것을 무시할 수 있습니다.fallthrough
는 원하는 만큼 여러 번 사용 할 수 있습니다.- 원하는 만큼 많은
case
를 작성 할 수 있습니다.
'if
'와 'else if
'를 사용하는 여러 조건이 있는 경우Switch case
라고 하는 다른 구조를 사용하는 것이 더 명확해지는 경우가 많습니다. 이 접근 방식을 사용하여 조건을 한 번 작성한 다음 가능한 모든 결과와 각 결과에 대해 어떤 결과가 발생해야 하는지 나열합니다.
C 언어에서는 정수 타입만 들어갈 수 있었지만, swift에서는 switch
구문의 조건에 다양한 값이 들어갈 수 있습니다. 다만 각 case
에 들어갈 비교 값은 입력 값과 데이터 타입이 같아야 합니다. 또, 비교될 값이 명확히 한정적인 값이 아닐 때는 default
를 꼭 작성해줘야 합니다. 또한 각 case
에는 범위 연산자를 사용할 수도, where
절을 사용하여 조건을 확장할 수도 있습니다.
말이 어렵나요? 예문을 보면서 확인해 보도록 하겠습니다.
switch 입력 값 {
case 비교 값1
//실행 구문
case 비교 값2
//실행 구문
// 이 case를 마치고 switch 구문을 탈출하지 않음. 아래 case로 계속 진행
fallthrough
case 비교 값3, 비교 값4, 비교 값5 // 한 번에 여러 값과 비교 가능
break // 탈출(종료)
default : // 한정된 범위가 명확하지 않다면 default사용 필수
//실행 구문
}
이제 switch
구문과 if else
문을 비교하면서 살펴보도록 하겠습니다.
let chr = "a"
if chr == "a" {
print("캐릭터는 a 입니다.")
}
else if chr == "b" {
print("캐릭터는 b 입니다.")
}
//캐릭터는 a 입니다.
위 if
문을 Switch
문으로 바꾸면 아래 코드와 같습니다.
let chr = "a" //"b" 로 바꾸면 결과값은 "이것은 b 입니다."로 바뀜
switch chr {
case "a" :
print("이것은 a 입니다.")
case "b" :
print("이것은 b 입니다.")
default:
print("아무것도 선택되지 않았습니다.")
}
//이것은 a 입니다.
아래 if
문을 Switch
문으로 바꿔보세요.
func loveCalculator() {
let loveScore = Int.random(in: 0...100)
if loveScore > 80 {
print("당신은 서로 많이 사랑합니다.")
} if loveScore > 40 && loveScore <= 80 {
print("당신은 썸을 타고 있습니다.")
} else {
print("당신은 평생 혼자입니다..")
}
}
loveCalculator()
Switch
문
func loveCalculator() {
let loveScore = Int.random(in: 0...100)
switch loveScore {
case 81..100:
print("당신은 서로 많이 사랑합니다.")
case 41..<81:
print("당신은 썸을 타고 있습니다.")
case ...40:
print("당신은 평생 혼자입니다..")
default:
print("다시 실행해주세요")
let weather = "sunny"
switch weather {
case "rain":
print("Bring an umbrella")
case "snow":
print("Wrap up warm")
case "sunny":
print("Wear sunscreen")
default:
print("Enjoy your day!")
}
위에 코드처럼 작성하게 되면 프린트 값 "wear sunscreen"을 반환받게 됩니다. 각 case
에는 break
가 자동 설정 되어서 true
값을 얻게 되면 자동으로 구문에서 빠져나오게 됩니다.
하지만 break
값을 무시하고 다음 코드로 계속 실행하려면 fallthrough
를 구문에 추가해주면 됩니다,
switch weather {
case "rain":
print("Bring an umbrella")
case "snow":
print("Wrap up warm")
case "sunny":
print("Wear sunscreen")
fallthrough
default:
print("Enjoy your day!")
}
//Wear sunscreen
//Enjoy your day!
let liveAlbums = 2
switch liveAlbums {
case 0:
print("첫번째")
case 1:
print("두번째")
case 2:
print("세번째")
default:
print("default")
}
//세번째
let liveAlbums = 5
switch liveAlbums {
case 0...1:
print("첫번째")
case 2...3:
print("두번째")
case 4...5:
print("세번째")
default:
print("default")
}
//세번째
let integerValue: Int = 5
switch integerValue {
case 0:
print("Value == zero")
case 1...100:
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
integerValue
의 값이 5이기때문에 switch
의 case
1...100을 충족시켰고, fallthrough
키워드를 사용하여 다음 case
도 실행되도록 했기 때문에 case
블록 3이 실행되서 출력된 것을 확인할 수 있습니다.
다양한 값 타입 사용
switch
구문의 입력 값으로 숫자 표현이 아닌 문자, 문자열, 열거형, 튜플, 범위, 패턴이 적용된 타입 등 다양한 타입의 값도 사용 가능합니다.
let stringValue: String = "서근 개발노트"
switch stringValue {
case "서근":
print("안녕하세요 서근입니다.")
case "미진":
print("안녕하세요 미진입니다.")
case "포뇨", "소피아", "캘시퍼":
print("안녕하세요. \(stringValue)")
default:
print("안녕하세요 \(stringValue)에 찾아와주셔서 감사드립니다")
}
// 안녕하세요 서근 개발노트에 찾아와주셔서 감사드립니다
위 case
블럭의 "포뇨", "소피아", "캘시퍼": 처럼 여러 개의 항목을 항 번에 case
로 지정해주는 것도 가능합니다. 그렇지만 여러 항목을 나타내기 위해 case
를 연달아 쓰는 것은 불가능합니다. case XXX:
다음에는 꼭 실행 가능한 코드가 위치해야 합니다.
잘못된 case 사용
let stringValue: String = "서근 개발노트"
switch stringValue {
case "서근":
print("안녕하세요 서근입니다.")
case "하울":
//실행될 코드가 없기 때문에 오류 발생
default:
print("안녕하세요 \(stringValue)에 찾아와주셔서 감사드립니다")
}
// 안녕하세요 서근 개발노트에 찾아와주셔서 감사드립니다
위처럼 "하울" case
에 실행 코드가 없기 때문에 컴파일 오류가 발생했씁니다. 만약 C 언어의 switch
처럼 break
를 사용하지 않은 경우 그 다음 case
블록을 실행하도록 했던 트릭을 swift에서 구현하고자 한다면 fallthrough
를 사용해야 합니다.
let stringValue: String = "서근 개발노트"
switch stringValue {
case "서근":
fallthrough
case "미진":
fallthrough
case "하울":
fallthrough
case "포뇨", "소피아", "캘시퍼":
print("안녕하세요. \(stringValue)")
default:
print("안녕하세요 \(stringValue)에 찾아와주셔서 감사드립니다")
}
// 안녕하세요 서근 개발노트에 찾아와주셔서 감사드립니다
튜플사용
typealias NameAge = (name: String, age: Int)
let tupleValue: NameAge = ("서근", 26)
switch tupleValue {
case ("미진", 20):
fallthrough
case ("서근", 26):
print("정확히 맞췄습니다! 저는 \(tupleValue.name) 입니다.")
default:
print("누굴 찾고 계신가요? 아마 당신의 이름은 \(tupleValue.name) 입니다.")
}
// 정확히 맞췄습니다! 저는 서근 입니다.
위 코드는 튜플이 굳이 필요하지 않습니다. 단지 예제 일 뿐이죠. 하지만 튜플은 이외에도 와일드카드 식별자와 함께 사용하면 좀 더 유용합니다. 와일드카드 식별자(_
) 는 switch
구문 외에도 여러 곳에 사용됩니다.
typealias NameAge = (name: String, age: Int)
let tupleValue: NameAge = ("서근", 26)
switch tupleValue {
case ("미진", _):
fallthrough
case ("서근", _):
print("이름만 맞췄습니다! 제 나이는 \(tupleValue.age)살 입니다.")
fallthrough
case (_, 26):
print("나이만 맞췄습니다! 제 이름은 \(tupleValue.name) 입니다.")
default:
print("누굴 찾고 계신가요? 아마 당신의 이름은 \(tupleValue.name) 입니다.")
}
/*
이름만 맞췄습니다! 제 나이는 26살 입니다.
나이만 맞췄습니다! 제 이름은 서근 입니다.
*/
where 키워드 사용
where
키워드를 사용하여 case
의 조건을 확장할 수 있습니다. where
에 관한 문법은 다음에 따로 게시물로 다루겠습니다.
let IceCream: String = "비비빅"
let price: Int = 400
let isDelicious: Bool = false
switch IceCream {
case "비비빅" where isDelicious == true:
print("아주 맛있다!")
case "비비빅" where price < 1000 && isDelicious == false:
print("\(IceCream)...? 제가 별로 싫어하는것을 사오셨네요..")
case "비비빅" where price > 200:
print("와 엄청 싸다!")
case "메로나":
print("메로나")
default:
print("맛이 없네요...")
}
// 비비빅...? 제가 별로 싫어하는것을 사오셨네요..
열거형 사용
열거형과 같이 한정된 범위의 값을 입력 값으로 받게 될 때 값에 대응하는 각 case
를 구현한다면 default
를 구현하지 않아도 됩니다. 만약 값에 대응하는 각 case
를 구현하지 않는다면 default
는 필수입니다.
enum School {
case 유치원, 초등학교, 중학교, 고등학교, 대학교
}
let 나의학력: School = .대학교
switch 나의학력 {
case .유치원:
print("저의 최종학력은 \(School.유치원) 입니다.")
case .초등학교:
print("저의 최종학력은 \(School.초등학교) 입니다.")
case .중학교:
print("저의 최종학력은 \(School.중학교) 입니다.")
case .고등학교:
print("저의 최종학력은 \(School.고등학교) 입니다.")
case .대학교:
print("저의 최종학력은 \(School.대학교) 입니다.")
}
// 저의 최종학력은 대학교 입니다.
Unknown
만약 열거형에 case
가 추가될 가능성이 있다면 switch
구문에서는 어떻게 해야 할까요?
위 코드처럼 열거형에 정의한 모든 case
를 처리해주면 정상적으로 컴파일되겠지만, 나중에 열거형에 case
를 추가한다면 기존의 switch
구문은 컴파일 오류가 발생하게 될 것입니다. switch
구문은 모든 case
에 대해 대비하지 못하기 때문이죠. 이럴 때는 unknown
이라는 속성을 사용하여 대처할 수 있습니다.
enum Menu {
case Pizza
case Chicken
}
let lunchMenu: Menu = .Pizza
switch lunchMenu {
case .Chicken:
print("양념치킨")
case .Pizza:
print("도미노피자!")
case _: // default와 같은 표현
print("치킨소스 추가해주세요")
}
//도미노피자!
Menu
라는 열거형에 나중에 case를
추가할 거 같아서 해당 열거형의 값을 처리하는 switch
구문의 마지막 case로
와일드카드 case(_)
를 미리 추가했습니다. 그러면 나중에 Menu
열거형에 case
를 추가해도 switch
구문에서 컴파일 오류가 발생하지 않게 됩니다.
그런데 만약 나의 동료 또는 제가 나중에 Menu
열거형에 새로운 case
를 추가했다고 해볼게요. 그리고 구현해둔 switch
구문의 내부 코드를 수정하지 않았다고 가정해보겠습니다. 그러면 오히려 case _
의 상황이 발생할 가능성이 있기 때문에 문법적으로 오류가 없지만 논리적으로 오류가 발생할 수 있는 충분한 여지가 생기게 됩니다. 이런 문제를 방지하기 위해 unknown
속성을 사용할 수 있습니다.
enum Menu {
case Pizza
case Chicken
case Hamburger
}
let lunchMenu: Menu = .Pizza
switch lunchMenu {
case .Chicken:
print("양념치킨")
case .Pizza:
print("도미노피자!")
@unknown case _: // default와 같은 표현
print("치킨소스 추가해주세요")
}
이렇게 Menu
열거형에 Hamburger case
를 추가했고, case _:
앞에 unknown
속성을 추가했습니다. unknown
속성을 부여해주면 case _
에서 아래와 같이 경고가 발생합니다.
모든 switch
구문이 모든 case
에 대응하지 않는다는 컴파일러 경고를 주고 있네요. 이처럼 논리적인 오류에 대해 도움받을 수 있는 unknown
속성을 부여할 수 있는 case
는 위 코드처럼 case _
혹은 default case
뿐입니다. 또, unknown
속성을 부여한 case
는 switch
구문의 가장 마지막에 case
로 작성해야 합니다.
언제 if를 대신에서 Switch문을 사용해야 하나요??
switch
구문은 변수를 입력받아 미리 정해놓은 여러 값들과의 일치 여부를 판단하여 switch
문 내의 control flow
를 결정합니다.
if else
구문은 불리언의 결과 값을 내놓는 조건문에 따라 true
, false
에 해당하는 각각 두 개의 흐름으로 갈라집니다.
if else
문을 중첩되게 배치하면, 두 개의 흐름뿐만 아니라 세 개, 네 개 등등.. 그 이상의 control flow을 가질 수 있게 됩니다.(if
/ else if
/ else
와 같은 방식)
if else
구문을 쓸 수 있는 모든 상황에 switch
문을 쓸 수 있는 건 아니지만, 반대로 모든 switch
구문은 if else
문으로 대체될 수 있습니다.
즉, 하나의 변수를 입력받아 그 변수의 값에 따라 다른 흐름으로 이동할 수 있는 코드를 짜야할 때에 switch
문과 if else
구문이 둘 다 사용될 수 있음을 알 수 있습니다.
결론부터 말하자면, switch
문을 사용하는 것이 좋습니다.
Switch TEST : 문제를 풀려면 이곳을 클릭해주세요.
지금까지 배운 것을 요약하자면...
- Swift에는 산술과 비교를 위한 연산자가 있습니다.
- 변수를 수정하는 산술 연산자의 복합 변형이 있습니다 :
+=
,-=
등 if
,else
및else if
조건의 결과에 따라 코드를 실행합니다.- Swift에는
true
및false
에 따라 조건을 실행하는 삼항 연산자가 있습니다. - 동일한 값을 사용하는 여러 조건이 있는 경우
if
대신switch
를 사용하는 것이 더 명확합니다. - 범위인
..<
와...
마지막 숫자가 제외인지 또는 포함해야 하는지 여부에 따라 달라집니다.
읽어주셔서 감사합니다🤟
'SWIFT > Grammar' 카테고리의 다른 글
Swift : 기초문법 [While 루프] (0) | 2021.02.21 |
---|---|
Swift : 기초문법 [For 루프] (1) | 2021.02.21 |
Swift : 기초문법 [삼항 연산자 - ternary operator] (0) | 2021.02.20 |
Swift : 기초문법 [논리 연산자 - Logical Operators] (0) | 2021.02.20 |
Swift : 기초문법 [ iF / else if / else ] (0) | 2021.02.20 |