Swift 다양한 control flow 구문을 제공합니다. while 문 같은 경우는 특정 task 를 여러번 반복할 수 있게 해주고, if guard swiftch 문 같은 경우에는 특정 상황에 기반해 코드의 여러 분기점을 만들어 실행하게 해줍니다.
또한 break 와 continue 키워드는 실행의 흐름을 코드의 드른 부분으로 옮겨줍니다.
for in loop 에서는 어레이, 딕셔너리, range, string 그리고 여러 열거 타입들을 순회 할수 있습니다.
switch 문은 C 언와 같은 다른 언어들과 비교될 정도로 강력한 기능을 가집니다. Case 들은 다양한 패턴과 매칭됩니다.
For-In Loops
열거형 타입을 순회하기 위해서는 for in 문을 사용합니다.
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
print("Hello, \(name)!")
}
// Hello, Anna!
// Hello, Alex!
// Hello, Brian!
// Hello, Jack!
Swift
복사
어레이의 순환
딕셔너리 또한 순회가 가능합니다. 딕셔너리의 가각의 항목은 (key, value) 튜플로써 반환되며, 이를 decompose 하여 for in loop 안에서 사용이 가능합니다.
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
print("\(animalName)s have \(legCount) legs")
}
// cats have 4 legs
// ants have 6 legs
// spiders have 8 legs
Swift
복사
딕셔너리의 순회
딕셔너리 같은 경우 순서가 없기 때문에 재실 행시 같은 순서로 실행될 것이라는 보장을 하지 않습니다.
for index in 1...5 {
print("\(index) times 5 is \(index * 5)")
}
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25
Swift
복사
numeric ranges 또한 순회가 가능합니다.
범위 연산자 ... 를 활용하여 특정 범위의 정수를 순회할 수 있습니다.
위의 예시에서 알 수 있듯이for in loop 에서
1.
index 값은 상수로 선언되며 코드가 반복될 때 마다 재 생성 됩니다. 또한
2.
index 는 미리 선언하지 않아도 사용이 가능합니다.
(loop 문 내에서 암묵적으로 선언 됩니다.) let 키워드가 필요하지 않습니다.
열거형 내부에서 값이 필요하지 않다면, 언더스코어 _ 를 활용해서 변수의 이름을 대신할 수 있습니다.
즉 반복 횟수만 지정한 반복이 필요할 경우, _ 를 활용해 불필요한 할당을 방지해줍니다.
let base = 3
let power = 10
var answer = 1
for _ in 1...power {
answer *= base
}
print("\(base) to the power of \(power) is \(answer)")
// Prints "3 to the power of 10 is 59049"
Swift
복사
half-open 연산자를 사용해서 마지막 값을 제외하고 순회할 수 있습니다.
let minutes = 60
for tickMark in 0..<minutes {
// render the tick mark each minute (60 times)
}
Swift
복사
stride(from:to:by:) 함수를 사용해서 원하지 않는 값을 건너 뛸 수 있습니다.
let minuteInterval = 5
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
// render the tick mark every 5 minutes (0, 5, 10, 15 ... 45, 50, 55)
}
Swift
복사
stride(from:through:by:) 를 이용해서 마지막 값을 포함해 순회할 수 있습니다.
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
// render the tick mark every 3 hours (3, 6, 9, 12)
}
Swift
복사
Seaquence 프로토콜을 준수하는 모든 타입은 for - in loop 내에서 순회가 가능합니다.
While Loops
while loop 는 조건이 false 가 될 때까지 반복을 수행합니다. 이러한 종류의 loop 는 숫자 타입의 순회 사용시 적합합니다. Swift 는 두가지 형태의 while loop 를 제공합니다.
•
while : loop 의 시작 부분에서 조건을 검사합니다.
•
repeat-while : loop 의 마지막 부분에서 조건을 검사합니다.
While
while loop 는 하나의 조건을 평가하면서 시작됩니다. 조건이 true 면 내부의 코드블럭이 실행되고 false 가 될 때까지 이 코드블럭을 반복적으로 수행합니다.
while condition {
statements
}
Swift
복사
Repeat-While
while loop 의 변형형으로, 먼저 loop 블록을 한번 실행한뒤에 loop 의 조건을 검사하고, 조건이 참이면 loop 를 한번 더 반복한다.
repeat {
statements
} while condition
Swift
복사
Conditional Statesments
조건문을 활용해 상황에 따라 다른 코드가 실행되도록 할 수 있습니다. Swift 에는 code 를 분기할 수 있는 두가지 방법인 switch 와 if 문을 제공합니다.
일반적으로 if 문은 단순한 조건을 판단하기에 적합하고, switch 문은 만은 가능성이 존재할 때 사용됩니다.
If
아래는 if 문의 가장 간단한 형태입니다
var temperatureInFahrenheit = 30
if temperatureInFahrenheit <= 32 { // 조건이 참이면
print("It's very cold. Consider wearing a scarf.") //출력
}
// Prints "It's very cold. Consider wearing a scarf."
Swift
복사
조건이 참이면 중괄호 안의 코드가 실행됩니다.
아래는 else 키워드를 사용한 코드 예제입니다.
else 문 뒤에오는 중괄호 안의 코드들은 조건이 거짓일 경우 실행됩니다.
temperatureInFahrenheit = 40
if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
} else {
print("It's not that cold. Wear a t-shirt.")
}
// Prints "It's not that cold. Wear a t-shirt."
Swift
복사
조건은 항상 참 또는 거짓이므로 두 코드블럭 중 하나는 무조건 실행됩니다.
여러개의 if 문을 이어서 사용이 가능합니다.
temperatureInFahrenheit = 90
if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
print("It's really warm. Don't forget to wear sunscreen.")
} else {
print("It's not that cold. Wear a t-shirt.")
}
// Prints "It's really warm. Don't forget to wear sunscreen."
Swift
복사
else 의 사용은 선택가능한 사항입니다. 상황에 따라서 생략이 가능합니다.
temperatureInFahrenheit = 72
if temperatureInFahrenheit <= 32 {
print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
print("It's really warm. Don't forget to wear sunscreen.")
}
Swift
복사
Switch
switch 문은 하나의 값을 여러개의 가능한 패턴과 비교합니다. 첫번째로 일치하는 적절한 코드 블럭을 실행하게 됩니다. 많은 잠재적 상황이 존재할 시 if 문 대신 사용하세요
아래는 switch 문의 기본 사용법입니다.
switch some valueToConsider {
case value1:
//valueToConsider 이 value1 값과 같을 때 실행되는 블럭
case value2,
value3:
//valueToConsider 이 value1 값과 같을 때 실행되는 블럭
default:
//valueToConsider 이 value1 값과 같을 때 실행되는 블럭
}
Swift
복사
switch 문은 여러가지 가능한 경우의 수를 case 키워드로 정의합니다.
Swift 에서는 더 복잡한 패턴을 다룰 수 있도록 여러가지 방안을 제공합니다.
switch 문에서는 반드시 발생가능한 모든 case 를 다루어야합니다.
만약 모든 case 가 복잡한 패턴을 가진다면 default 키워드를 사용하여서 나머지 경우의 수들을 한번에 다룰 수 있습니다. default 키워드는 반드시 맨 마지막에 위치해야합니다.
let someCharacter: Character = "z"
switch someCharacter {
case "a":
print("The first letter of the alphabet")
case "z":
print("The last letter of the alphabet")
default:
print("Some other character")
}
// Prints "The last letter of the alphabet"
Swift
복사
No Implicit Fallthrough
C 와 Objective C 에서의 switch 문은 기본적으로 모든 case 들을 하나씩 검사합니다. 하지만 Swift 의 switch 문은
그대신 만약 첫번째로 일치하는 case 가 존재한다면 switch 문을 종료합니다.
따라서 단 하나의 case 문만이 실행됩니다.
break 키워드를 사용해서 특정 case 에 대해서 해당 case 의 코드 실행을 종료, switch 문을 탈출할 수 있습니다.
각각의 case 들은 적어도 하나의 실행가능한 코드를 가져야합니다. 그렇지 않다면 컴파일 에러를 발생시킴니다.
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a": // Invalid, the case has an empty body
case "A":
print("The letter A")
default:
print("Not the letter A")
}
// This will report a compile-time error.
Swift
복사
위 코드같은 경우 아래와 같이 고쳐쓸 수 있습니다.
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a", "A": // 여러개의 케이스를 묶을 수 있음
print("The letter A")
default:
print("Not the letter A")
}
// Prints "The letter A"
Swift
복사
이렇게 결합된 case 들은 가독성을 위해 여러줄로 작성될 수 있습니다.
fallthrough 키워드를 사용해서 특정 case 에서 일치한다 해도 모든 case 들과 비교를 진행합니다.
Interval Matiching
switch 문안의 case 들은 구간내의 포함여부를 체크할 수 있습니다.
let approximateCount = 62
let countedThings = "moons orbiting Saturn"
let naturalCount: String
switch approximateCount {
case 0:
naturalCount = "no"
case 1..<5:
naturalCount = "a few"
case 5..<12:
naturalCount = "several"
case 12..<100:
naturalCount = "dozens of"
case 100..<1000:
naturalCount = "hundreds of"
default:
naturalCount = "many"
}
print("There are \(naturalCount) \(countedThings).")
// Prints "There are dozens of moons orbiting Saturn."
Swift
복사
Tuples
Switch 문에서 다수의 값을 한번에 비교하기 위해 tuple 을 사용할 수 있습니다. 각각의 튜플 원소들은 다른 구간, 다른 값들의 구간에 대해 test 를 받게 됩니다. 대신 언더스코어를 활용해서 특정 원소의 비교를 무시할 수 있습니다.
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
print("\(somePoint) is at the origin")
case (_, 0):
print("\(somePoint) is on the x-axis")
case (0, _):
print("\(somePoint) is on the y-axis")
case (-2...2, -2...2):
print("\(somePoint) is inside the box")
default:
print("\(somePoint) is outside of the box")
}
Swift
복사
만약 위 코드에서 somePoint 가 (0,0) 에 해당한다면 (0,0)아래의 case 들은 모두 무시됩니다.
Value Bindings
switch case 에서 임시 값을 상수 또는 변수에 저장할 수 있습니다. 이를 value binding 이라고 합니다. 이 임시 값은 case 문 내에서 임시로 사용되며, 그 case 문이 종료되면 유효하지 않습니다,
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
print("on the x-axis with an x value of \(x)")
case (0, let y):
print("on the y-axis with a y value of \(y)")
case let (x, y):
print("somewhere else at (\(x), \(y))")
}
// Prints "on the x-axis with an x value of 2"
Swift
복사
이 swtich 문에는 default 케이스가 정의되지 않았습니다. anotherPoint 가 항상 두개의 값을 가지는 튜플이므로 마지막 case 에 항상 대응 되므로 default case 가 필요하지 않습니다.
Where
Where 절을 사용해서 추가 조건을 검사할 수 있습니다. 앞서 논의한 임시 값을 활용해 추가조건을 생성할 수 있습니다. where 절의 조건이 참이어야지만 case 문이 실행됩니다.
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
print("(\(x), \(y)) is just some arbitrary point")
}
// Prints "(1, -1) is on the line x == -y"
Swift
복사
마찬가지로 마지막 case 가 모든 가능한 상황을 포괄하므로 default case 가 필요없습니다.
Compound Cases
콤마를 사용해 여러개의 패턴들을 하나의 case 문에 적용할 수 있습니다.
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
print("\(someCharacter) is a consonant")
default:
print("\(someCharacter) isn't a vowel or a consonant")
}
// Prints "e is a vowel"
Swift
복사
value binding 을 포함하는 case 문에도 마찬가지로 콤마를 활용해 여러개의 패턴에 대한 동일한 로직을 작성할 수 있습니다.
let stillAnotherPoint = (9, 0)
switch stillAnotherPoint {
case (let distance, 0), (0, let distance):
print("On an axis, \(distance) from the origin")
default:
print("Not on an axis")
}
// Prints "On an axis, 9 from the origin"
Swift
복사
Control Transfer Statements
Control Transfer 문은 코드의 실행 순서를 바꿀 수 있도록 합니다.
5개의 Control Transfer 문이 존재합니다.
•
continue
•
break
•
fallthrough
•
return
•
throw
Continue
continue 문은 현재 코드의 동작을 멈추고 실행 순서를 다음 loop 로 옮기는 것을 의미합니다.
let puzzleInput = "great minds think alike"
var puzzleOutput = ""
let charactersToRemove: [Character] = ["a", "e", "i", "o", "u", " "]
for character in puzzleInput {
if charactersToRemove.contains(character) {
continue // 다음 순회로 넘어감
}
puzzleOutput.append(character)
}
print(puzzleOutput)
// Prints "grtmndsthnklk"
Swift
복사
Break
break 문은 전체 control flow 문을 즉시 종료합니다. switch 나 loop 문에서 사용이 가능합니다.
Break in a Loop Statement
loop 의 실행을 즉시 종료하고 loop 의 다음으로 코드의 실행순서를 변경합니다.
어떠한 현재 loop 의 코드도 실행되지않으며 다음 loop 또한 실행되지 않습니다.
Break in a Switch Statement
switch 문 내에서 사용되면 switch 문의 실행을 즉시 종료하고, switch 문의 중괄호 다음으로 코드의 실행순서를 옮깁니다.
여러개의 case 들을 무시할 수 있도록 합니다. Switch 문에서는 빈 case 들을 허용 하지 않으나 ,, 몇몇의 case 에 대해서는 break 문을 사용함으로써 동작을 구현하지 않을 수 있습니다.
즉 무시하고 싶은 case 에 대해 break 키워드를 사용할 수 있습니다.
let numberSymbol: Character = "三" // Chinese symbol for the number 3
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "١", "一", "๑":
possibleIntegerValue = 1
case "2", "٢", "二", "๒":
possibleIntegerValue = 2
case "3", "٣", "三", "๓":
possibleIntegerValue = 3
case "4", "٤", "四", "๔":
possibleIntegerValue = 4
default:
break // 다른 경우의 수에 대해서는 어떠한 코드도 실행하고 싶지 않을 때,
}
if let integerValue = possibleIntegerValue {
print("The integer value of \(numberSymbol) is \(integerValue).")
} else {
print("An integer value couldn't be found for \(numberSymbol).")
}
// Prints "The integer value of 三 is 3."
Swift
복사
Fallthough
Swift 에서 switch 문은 특정 case 와 일치하게 되면 나머지 case 들을 검사하지 않습니다. 이러한 기본적인 셋팅을 바꾸어 일치하더라도 나머지 case 들에 대해서 검사를 진행하려면 fallthrough 키워드를 사용하면 됩니다.
let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += " a prime number, and also"
fallthrough
default:
description += " an integer." // 이 코드도 실행됩니다.
}
print(description)
// Prints "The number 5 is a prime number, and also an integer."
Swift
복사
Labeled Statements
루프 또는 여러 조건문들이 중첩되게 되면 위에서 언급한 control transfer 문들이 어떤 루프에 영향을 미치는 지가 불분명 할 수 있습니다.
따라서 이를 명시할 수 있습니다.
1.
먼저 loop 에 이름을 붙여야합니다.
2.
control transfer 문과 함께 loop 의 이름을 명시합니다.
gameLoop: while square != finalSquare {
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare:
// diceRoll will move us to the final square, so the game is over
break gameLoop // switch 문이 아닌 while 문을종료
case let newSquare where newSquare > finalSquare:
// diceRoll will move us beyond the final square, so roll again
continue gameLoop
default:
// this is a valid move, so find out its effect
square += diceRoll
square += board[square]
}
}
print("Game over!")
Swift
복사
이처럼 변경하고자 하는 control flow 의 대상을 명확히 할 수 있습니다.
위 예시에서 loop 는 while 문 하나이므로 continue 에 한해서는 label 을 작성하지 않아도 그 대상이 명확하기 때문에 사용할 필요가 없습니다.
Early Exit
guard 문을 활용하면 if 문 처럼 특정 코드에 대한 실행 여부를 Boolean 표현식 에 기반해 결정할 수 있습니다.
함수가 실행되기 위한 선행조건을 만족하는 지를 확인하는데 자주 사용됩니다.
func greet(person: [String: String]) {
guard let name = person["name"] else {
return // name 의 key 값이 존재하지 않는다면 함수 실행 종료
}
print("Hello \(name)!") // 이를 사용해야하기 떄문입니다.
guard let location = person["location"] else {
print("I hope the weather is nice near you.")
return
}
print("I hope the weather is nice in \(location).")
}
greet(person: ["name": "John"])
// Prints "Hello John!"
// Prints "I hope the weather is nice near you."
greet(person: ["name": "Jane", "location": "Cupertino"])
// Prints "Hello Jane!"
// Prints "I hope the weather is nice in Cupertino."
Swift
복사
guard 문은 옵셔널 바인딩을 통해 값을 name 에 할당합니다.
만약 값이 존재하지 않는다면(nil) else 이후의 코드블럭이 실행됩니다.
여기서는 return 이 실행되며, return 대신 다른 control transfer 문들 또한 실행이 가능합니다(break, continue, or throw)
gaurd 문을 코드 실행에 필요한 선행 조건으로 사용한다면 if 문 보다, 코드의 가독성이 증가합니다.
Checking API Availability
Swift 에는 API 의 사용 가능성을 점검하기 위한 빌트인 기능이 존재합니다. 이 기능은 주어진 target 의 배치에 있어서 API 의 사용이 불가능할 때, 실수로 API 를 사용하지 않도록 보장해줍니다.
컴파일러는 SDK 의 내의 사용가능성에 대한 정보를 사용하여 특정 코드의 배치 내에서 API 가 사용 가능한지를 확인합니다. 만약 API 가 사용가능하지 않다면 Swift 는 컴파일 에러를 발생시킵니다.
if 또는 guard 문에 availability condition 을 사용할 수 있습니다. API 가 사용가능한지에 따라 코드의 실행여부를 결정할 수 있습니다. 또한 컴파일러는 availability condition 으로부터 API 의 사용가능성 에 대한 정보를 얻어와 사용할 수 있습니다.
if #available(iOS 10, macOS 10.12, *) {
// Use iOS 10 APIs on iOS, and use macOS 10.12 APIs on macOS
} else {
// Fall back to earlier iOS and macOS APIs
}
Swift
복사
if #available 문을 사용해 특정 코드가 특정 플랫폼의 버전 이상에서만 사용가능하도록 구성할 수 있습니다.
#available은 여러 플랫폼에서 서로 다른 논리 처리를 결정하기 위해서 if 또는 guard문과 같이 사용됩니다.
즉, Bool을 반환하는 런타임 검사입니다.
주의할 점은, 해당 버전을 포함하여 그 이상의 버전"인지를 확인합니다.