1. For-In Loops πŸ‘©β€πŸ’»

For-In λ°˜λ³΅λ¬Έμ€ Array κ°€ μ €μž₯ν•œ items, String 이 μ €μž₯ν•œ characters와 같은 sequenceλ₯Ό λ°˜λ³΅ν•  수 μžˆλ‹€.

1. Iterate over with numeric ranges

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


  • λ§Œμ•½, μƒμˆ˜λ₯Ό 인자둜 받을 ν•„μš”κ°€ μ—†λ‹€λ©΄ _λ₯Ό μ΄μš©ν•΄ μ„±λŠ₯을 ν–₯μƒμ‹œν‚¬ 수 μžˆλ‹€
let base = 3
let power = 10
var answer = 1
for _ in 1...power {
    answer *= base
}
print("\(base) to the power of \(power) is \(answer)")  // 3 to the power of 10 is 59049


  • stride(from:to:by:)λ₯Ό μ΄μš©ν•˜λ©΄ from..<to λ²”μœ„λ₯Ό by만큼 step을 λ„£μ–΄ sequenceλ₯Ό λ§Œλ“€ 수 μžˆλ‹€
let sequence = stride(from: 0, to: 60, by: 5)
print(type(of: sequence))   // StrideTo<Int>
for tickMark in stride(from: 0, to: 60, by: 5) {
    print(tickMark, terminator: " ")    // 0 5 10 15 20 25 30 35 40 45 50 55
}


2. Iterate over the items in an array

let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
    print("Hello, \(name)!")
}
Hello, Anna!
Hello, Alex!
Hello, Brian!
Hello, Jack!


3. Iterate over a dictionary to access its key-value paris

μš°λ¦¬λŠ” Iterating over a dictionaryμ—μ„œ μ‚΄νŽ΄λ³Έ 것 처럼 Dictionary λŠ” ν•œ 쌍의 Kye: Value elements λ₯Ό tuple둜 μ ‘κ·Όν•΄ λ°˜λ³΅ν•  수 μžˆλ‹€.
μ•„λž˜λŠ” animalNameμ΄λΌλŠ” Key constant 와 legCountλΌλŠ” Value constant λ₯Ό κ°–λŠ” tuple 둜 λΆ„ν•΄λ˜λŠ” μ˜ˆμ œλ‹€.

let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
    print("\(animalName)s have \(legCount) legs")
}
cats have 4 legs
spiders have 8 legs
ants have 6 legs

2. While Loops πŸ‘©β€πŸ’»

μš°μ„  μ•„λž˜ while을 μ„€λͺ…ν•˜λ©΄μ„œ μ‚¬μš©ν•  μ£Όμ‚¬μœ„ ν•¨μˆ˜λŠ” λ‹€μŒκ³Ό κ°™λ‹€.

func rollDice() -> Int {
  Int.random(in: 1...6)
}

1. While

while λ°˜λ³΅λ¬Έμ€ 쑰건이 falseκ°€ 될 λ•ŒκΉŒμ§€ λ°˜λ³΅μ„ κ³„μ†ν•œλ‹€. 이것은 loop κ°€ μ‹œμž‘λ  λ•Œ μ •ν™•ν•œ 반볡 횟수λ₯Ό μ•Œ 수 μ—†λŠ” 경우 μœ μš©ν•˜κ²Œ μ‚¬μš©λ  수 μžˆλ‹€.

Syntax

while condition {
    statements
}


Q) μ£Όμ‚¬μœ„λ₯Ό 2개 κ΅΄λ € κ³±ν•œ 값이 20 이상이면 λ°˜λ³΅λ¬Έμ„ μ€‘μ§€ν•˜λΌ.
-> 반볡 횟수λ₯Ό μ•Œ 수 μ—†λ‹€.
-> while μ‚¬μš©μ΄ μ ν•©ν•˜λ‹€.

var result = 0
var rollCount = 0

while result < 20 {
    result = rollDice() * rollDice()
    rollCount += 1
    print(result)
}
print("The dice are rolled \(rollCount) times.")
10
4
36
The dice are rolled 3 times.

2. Repeat-While

repeat-while이 whileκ³Ό λ‹€λ₯Έ 점은 λ°˜λ³΅ν•  λ‘œμ§μ„ λ¨Όμ € μ‹€ν–‰ ν›„ 쑰건을 κ²€μ‚¬ν•œλ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— repeat-while은 μ΅œμ†Œν•œ 1λ²ˆμ€ λ‘œμ§μ„ μˆ˜ν–‰ν•œλ‹€.

Syntax

repeat {
    statements
} while condition


μœ„ μ£Όμ‚¬μœ„ λ¬Έμ œμ—μ„œ result 의 μ΄ˆκΉƒκ°’μ΄ 20보닀 크게 μ •ν•΄μ Έ μžˆλ‹€κ³  κ°€μ •ν•΄λ³΄μž.

var result = 25
var rollCount = 0

while result < 20 {
    result = rollDice() * rollDice()
    rollCount += 1
    print(result)
}

μœ„ λ‘œμ§μ€ 첫 condition 이 false μ΄λ―€λ‘œ while λ‚΄λΆ€λŠ” μ‹€ν–‰ν•˜μ§€ μ•ŠλŠ”λ‹€.


μ΄λ²ˆμ—λŠ” μœ„ λ‘œμ§μ„ repeat-while 둜 λ°”κΏ”μ„œ μ‹€ν–‰ν•΄λ³Έλ‹€.

var result = 25
var rollCount = 0

repeat {
    result = rollDice() * rollDice()
    rollCount += 1
    print(result)
} while result < 20
print("The dice are rolled \(rollCount) times.")
1
3
18
4
24
The dice are rolled 5 times.

μ΄ˆκΉƒκ°’μ΄ 20 μ΄μƒμ΄μ§€λ§Œ 졜초 1회 싀행을 ν•œλ‹€. 그리고 μ΄λ•Œ κ³„μ‚°λœ result λŠ” condition 을 λ§Œμ‘±ν•˜λŠ” μž‘μ€ κ°’μœΌλ‘œ λ°”λ€” 경우 repeat을 λ°˜λ³΅ν•˜κ²Œλœλ‹€. λ”°λΌμ„œ Repeat-While은 μ΅œμ†Œ 1λ²ˆμ€ μ‹€ν–‰ν•˜λ―€λ‘œ 1 ~ n번의 λ°˜λ³΅μ„ ν•˜κ²Œ λœλ‹€.

3. While-True

μ—¬κΈ° 쑰금 νŠΉλ³„ν•œ λ°©μ‹μ˜ While문이 μžˆλ‹€.

While λ˜λŠ” Repeat-While 은 λ°˜λ³΅μ„ 계속할지 μ—¬λΆ€λ₯Ό true/false 둜 condition 에 λ„£μ–΄ 반볡 μ—¬λΆ€λ₯Ό κ²°μ •ν•œλ‹€.
반면 While-TrueλŠ” condition 은 항상 true λ₯Ό μ£Όκ³ , λ°˜λ³΅μ„ 쀑단할지 μ—¬λΆ€λ₯Ό if 둜 검사해 전체 While문을 νƒˆμΆœν•œλ‹€. λ”°λΌμ„œ, 일반적인 While, Repeat-While 쑰건의 λ°˜λŒ€(!condition)κ°€ λœλ‹€ (λ§Œμ•½, Logical NOT Operator(!) λŒ€μ‹  λ…Όλ¦¬μ μœΌλ‘œ λ°˜λŒ€μ˜ μΌ€μ΄μŠ€λ₯Ό 넣을 수 μžˆλ‹€λ©΄ κ·Έλ ‡κ²Œ ν•˜λŠ” 것이 μ„±λŠ₯상 이점을 κ°–λŠ”λ‹€).

Syntax

while true {
    statements
    
    if !condition {
        break
    }
}


  • !condition
var result = 25
var rollCount = 0

while true {
    result = rollDice() * rollDice()
    rollCount += 1
    print(result)
    
    if !(result < 20) {
        break
    }
}


  • else break
var result = 25
var rollCount = 0

while true {
    result = rollDice() * rollDice()
    rollCount += 1
    print(result)
    
    if result < 20 {
    } else {
        break
    }
}
print("The dice are rolled \(rollCount) times.")


  • logical opposite condition
var result = 25
var rollCount = 0

while true {
    result = rollDice() * rollDice()
    rollCount += 1
    print(result)
    
    if result >= 20 {
        break
    }
}
print("The dice are rolled \(rollCount) times.")

Repeat-While 둜직이 μ—†λŠ” 언어일 경우 μ΄λŸ°μ‹μœΌλ‘œ κ΅¬ν˜„ν•  수 μžˆμ§€λ§Œ, Swift λŠ” 이λ₯Ό μ§€μ›ν•˜λ―€λ‘œ λͺ…ν™•ν•œ μ½”λ“œ μ˜λ„ 전달 및 가독성을 μœ„ν•΄ Repeat-While둜 μ½”λ“œλ₯Ό μž‘μ„±ν•˜λŠ” 것이 μ’‹λ‹€.


3. Conditional Statements - If πŸ‘©β€πŸ’»

Swift λŠ” 쑰건에 따라 λ‹€λ₯Έ λ‘œμ§μ„ μˆ˜ν–‰ν•  수 μžˆλ„λ‘ If와 Switchλ₯Ό μ œκ³΅ν•œλ‹€. κ·Έ 쀑 Ifλ₯Ό μ•Œμ•„λ³Έλ‹€.

1. Single if statement

if λŠ” 쑰건이 만쑱될 λ•Œ μ‹€ν–‰ν•˜λŠ” λ‘œμ§μ„ μ •μ˜ν•  수 μžˆλ‹€.

let temperatureInCelsius = 32
if temperatureInCelsius > 28 {
    print("It's hot. Turn on the air conditioner.")
}

// It's hot. Turn on the air conditioner.

2. if statements with else clause

else clause λ₯Ό μ΄μš©ν•΄ if statement 의 쑰건을 λ§Œμ‘±ν•˜μ§€ μ•Šμ€ κ²½μš°μ— μ‹€ν–‰ν•˜λŠ” λŒ€μ•ˆ λ‘œμ§μ„ μ •μ˜ν•  수 μžˆλ‹€.

let temperatureInCelsius = 24
if temperatureInCelsius > 28 {
    print("It's hot. Turn on the air conditioner.")
} else {
    print("It's nice weather. Go out for a walk.")
}

// It's nice weather. Go out for a walk.

3. Chaining multiple if statements

else ifλ₯Ό μ΄μš©ν•΄ μ—¬λŸ¬ 개의 if 쑰건을 μ—°μ†μ μœΌλ‘œ 검사 ν•  수 μžˆλ‹€. 이 λ•Œ λ§Œμ‘±ν•˜λŠ” if λ₯Ό λ§Œλ‚˜λ©΄ λ‘œμ§μ„ μˆ˜ν–‰ ν›„ νƒˆμΆœν•œλ‹€.

let temperatureInCelsius = 3
if temperatureInCelsius > 28 {
    print("It's hot. Turn on the air conditioner.")
} else if temperatureInCelsius < 10 {
    print("It's cole. Turn on the boiler.")
} else {
    print("It's nice weather. Go out for a walk.")
}

// It's cole. Turn on the boiler.

else clause λŠ” μ–Έμ œλ‚˜ Optional 이기 λ•Œλ¬Έμ— ν•„μˆ˜κ°€ μ•„λ‹ˆλ‹€.


4. Conditional Statements - Switch πŸ‘©β€πŸ’»

Swift λŠ” 쑰건에 따라 λ‹€λ₯Έ λ‘œμ§μ„ μˆ˜ν–‰ν•  수 μžˆλ„λ‘ If 와 Switch μ œκ³΅ν•œλ‹€. κ·Έ 쀑 Switchλ₯Ό μ•Œμ•„λ³Έλ‹€.

1. Alternative to the if statement for multiple states

μ—¬λŸ¬ 개의 condition이 μ£Όμ–΄μ§€λŠ” 경우 if ~ else if ~ else if ... elseλŠ” switch문으둜 λŒ€μ²΄ ν•  수 μžˆλ‹€.

Syntax

switch some value to consider {
case value 1:
    respond to value 1
case value 2,
    value 3:
    respond to value 2 or 3
default:
    otherwise, do something else
}


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")
}

// The last letter of the alphabet


if statement μ—μ„œ elseλŠ” μ–Έμ œλ‚˜ Optionalμ΄μ§€λ§Œ switch λ¬Έμ—μ„œ defaultλŠ” ν•„μˆ˜λ‹€.
λ”°λΌμ„œ if λ₯Ό switch 둜 λ°”κΏ€ λ•Œ else λ₯Ό κ΅¬ν˜„ν•˜μ§€ μ•ŠλŠ” κ²½μš°λŠ” default 에 break 라도 λ„£μ–΄μ€˜μ•Όν•œλ‹€.

let someCharacter: Character = "u"
switch someCharacter {
case "a":
    print("The first letter of the alphabet")
case "z":
    print("The last letter of the alphabet")
default:
    break
}

// Nothing

TypeScript(JavaScript)와 같은 λ‹€λ₯Έ μ–Έμ–΄μ—μ„œλŠ” defaultκ°€ Optional인 κ²½μš°κ°€ μžˆμœΌλ‚˜ Swift μ—μ„œλŠ” ν•„μˆ˜λ‘œ κ΅¬ν˜„ν•΄μ•Όν•œλ‹€.

TypeScript λŠ” default κ°€ Optional 이라 κ΅¬ν˜„ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.

const anotherCharacter: string = "u"
switch (anotherCharacter) {
    case "a":
        console.log("The first letter of the alphabet")
        break
    case "z":
        console.log("The last letter of the alphabet")
        break
}

// Nothing

2. No Implicit Fallthrough

Objective-C λ₯Ό ν¬ν•¨ν•œ λŒ€λΆ€λΆ„μ˜ μ–Έμ–΄μ—μ„œ switch 의 μž‘λ™μ€ 처음 μΌμΉ˜ν•˜λŠ” case λ₯Ό μ‹€ν–‰ν•œ ν›„ μ•„λž˜ case λ₯Ό 계속 μ‹€ν–‰ν•΄ λ‚΄λ €κ°„λ‹€(fallthrough the bottom of each case).

const anotherCharacter: string = "z"
switch (anotherCharacter) {
    case "a":
    case "A":
        console.log("The first letter of the alphabet")
        break
    case "z":
    case "Z":
        console.log("The last letter of the alphabet")
        break
}

// The last letter of the alphabet


Swift 의 switch 문은 처음 μΌμΉ˜ν•˜λŠ” case λ₯Ό μ‹€ν–‰ν•œ ν›„ μ¦‰μ‹œ μ’…λ£Œλœλ‹€. λ”°λΌμ„œ Swift μ—μ„œ μ•„λž˜μ™€ 같은 λ‘œμ§μ€ 컴파일 μ—λŸ¬κ°€ λ°œμƒλœλ‹€.

let anotherCharacter: Character = "z"
switch anotherCharacter {
case "a":   // 'case' label in a 'switch' must have at least one executable statement
case "A":
    print("The first letter of the alphabet")
case "z":   // 'case' label in a 'switch' must have at least one executable statement
case "Z":
    print("The last letter of the alphabet")
default:
    print("Some other character")
}


λ”°λΌμ„œ Swift 의 switch 문은 β€˜breakβ€˜λ₯Ό λͺ…μ‹œν•˜μ§€ μ•Šμ•„λ„ λœλ‹€.
λ°˜λŒ€λ‘œ μ˜λ„μ μœΌλ‘œ fallthrough μ‹œν‚€κΈΈ μ›ν•˜λ©΄ fallthroughλ₯Ό λͺ…μ‹œν•΄μ•Όν•œλ‹€.

let anotherCharacter: Character = "z"
switch anotherCharacter {
case "a": fallthrough
case "A":
    print("The first letter of the alphabet")
case "z": fallthrough
case "Z":
    print("The last letter of the alphabet")
default:
    print("Some other character")
}

// The last letter of the alphabet


ν•˜μ§€λ§Œ μœ„μ™€ 같은 방식은 ꢌμž₯λ˜μ§€ μ•ŠλŠ”λ‹€. Swift λŠ” μΌμΉ˜ν•˜λŠ” case λ₯Ό μ‹€ν–‰ ν›„ μ¦‰μ‹œ μ’…λ£Œν•¨μœΌλ‘œμ¨ λŒ€λΆ€λΆ„μ˜ 경우 κ°œλ°œμžκ°€ switch λ¬Έμ—μ„œ break λ₯Ό 빠뜨렀 λ°œμƒν•˜λŠ” 논리적 였λ₯˜λ₯Ό μ˜ˆλ°©ν•  뿐 μ•„λ‹ˆλΌ λ‹€λ₯Έ μ–Έμ–΄μ—μ„œ single case match만 맀칭할 수 μžˆλŠ” 것과 달리 multiple case matchλ₯Ό ν•˜λ―€λ‘œ λ”λ”μš± fallthrough λŠ” ν•„μš”κ°€ μ—†λ‹€.

이것을 Compound Cases 라 ν•˜λ©° μ•„λž˜μ„œ λ‹€μ‹œ 닀루도둝 ν•œλ‹€.

let anotherCharacter: Character = "z"
switch anotherCharacter {
case "a", "A":
    print("The first letter of the alphabet")
case "z", "Z":
    print("The last letter of the alphabet")
default:
    print("Some other character")
}

// The last letter of the alphabet

가독성을 μœ„ν•΄ multiple case λ₯Ό μ€„λ°”κΏˆ ν•΄ 맀칭할 수 μžˆλ‹€.

3. Switch-True

μ—¬κΈ° 쑰금 νŠΉλ³„ν•œ λ°©μ‹μ˜ Switch문이 μžˆλ‹€.

1 ) Interval Matching

일반적으둜 Switch 문은 equal둜 맀칭되기 λ•Œλ¬Έμ— single case matchκ°€ 기본이닀. λ”°λΌμ„œ λ²”μœ„ λ§€μΉ­μ‹œ μ•„λž˜μ™€ 같이 μž‘μ„±ν•œλ‹€.

const approximateCount: number = 62
const countedThings: string = "moons orbiting Saturn"
let naturalCount: string
switch (true) {
    case approximateCount === 0:
        naturalCount = "no"
        break
    case (approximateCount >= 1) && (approximateCount < 5):
        naturalCount = "a few"
        break
    case (approximateCount >= 5) && (approximateCount < 12):
        naturalCount = "several"
        break
    case (approximateCount >= 12) && (approximateCount < 100):
        naturalCount = "dozens of"
        break
    case (approximateCount >= 100) && (approximateCount < 1000):
        naturalCount = "hundreds of"
        break
    default:
        naturalCount = "many"
}
console.log(`There are ${naturalCount} ${countedThings}.`)
There are dozens of moons orbiting Saturn.


λ§ˆμ°¬κ°€μ§€λ‘œ Swift 도 Interval Matching 을 μ‚¬μš©ν•˜μ§€ μ•Šκ³  λ‹€μŒκ³Ό 같이 Switch-True λ₯Ό μ΄μš©ν•΄ λ²”μœ„ 맀칭을 ν•  수 μžˆλ‹€.

let approximateCount: Int = 62
let countedThings: String = "moons orbiting Saturn"
let naturalCount: String
switch true {
case approximateCount == 0:
    naturalCount = "no"
case (approximateCount >= 1) && (approximateCount < 5):
    naturalCount = "a few"
case (approximateCount >= 5) && (approximateCount < 12):
    naturalCount = "several"
case (approximateCount >= 12) && (approximateCount < 100):
    naturalCount = "dozens of"
case (approximateCount >= 100) && (approximateCount < 1000):
    naturalCount = "hundreds of"
default:
    naturalCount = "many"
}
print("There are \(naturalCount) \(countedThings).")
There are dozens of moons orbiting Saturn.


2 ) Validation Check

Switch-True의 μš©λ²• 쀑 λ‹€λ₯Έ ν•˜λ‚˜λŠ” if ~ else if ~ else if ~ ... else ꡬ문보닀 λ”μš± κ°„κ²°ν•˜κ²Œ Validation Checkλ₯Ό ν•  수 μžˆλ‹€λŠ” 것이닀.

struct User {
    var name: String?
    var age: Int?
    var phone: String?
    var height: Double?
    var weight: Double?
}

func validateUser(of user: User?) -> Bool {
    guard let user = user else { return false }
    
    switch true {
    case user.age == nil: print("age is nil"); return false
    case (user.age! < 0) || (user.age! > 130): print("invalid age"); return false
    case user.name == nil: print("name is nil"); return false
    case user.phone == nil: print("phone is nil"); return false
    case user.height == nil: print("height is nil"); return false
    case user.weight == nil: print("weight is nil"); return false
    default: return true
    }
}


var myUser = User(name: "홍길동", age: 132, phone: "010-4434-3556", height: 183.2, weight: 74)

let result: Bool? = validateUser(of: myUser)
print("Validation check result of myUser is \(result!).")
invalid age
Validation check result of myUser is false.


var myUser = User(name: "μž₯보고", age: 42, phone: "010-2342-1234", height: 175.2, weight: nil)

let result: Bool? = validateUser(of: myUser)
print("Validation check result of myUser is \(result!).")
weight is nil
Validation check result of myUser is false.


var myUser = User(name: "μ΄μˆœμ‹ ", age: 30, phone: "010-7423-3464", height: 169.6, weight: 52)

let result: Bool? = validateUser(of: myUser)
print("Validation check result of myUser is \(result!).")
Validation check result of myUser is true.

μ •κ·œν‘œν˜„μ‹μ„ μ΄μš©ν•˜κ±°λ‚˜, Bool κ²°κ³Ό λŒ€μ‹  Exception을 throwν•˜λ„λ‘ ν•  μˆ˜λ„ μžˆλ‹€.

4. Interval Matching

Swift 의 switch 문은 multiple case matchλ₯Ό μ§€μ›ν•˜κΈ° λ•Œλ¬Έμ— Switch-True λŒ€μ‹  range operatorλ₯Ό μ΄μš©ν•΄ λ”μš± κ°„κ²°ν•œ μ½”λ“œλ‘œ λ²”μœ„ 맀칭을 ν•  수 μžˆλ‹€.

let approximateCount: Int = 62
let countedThings: String = "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).")
There are dozens of moons orbiting Saturn.

5. Tuples

_λŠ” whildcard pattern으둜 μ‚¬μš©λ˜μ–΄ μ–΄λ–€ 값이든 맀칭할 수 μžˆλ‹€.

func whereIs(_ point: (Int, Int)) {
    switch point {
    case (0, 0):
        print("\(point) is at the origin")
    case (_, 0):
        print("\(point) is on the x-axis")
    case (0, _):
        print("\(point) is on the y-axis")
    case (-2...2, -2...2):
        print("\(point) is inside the box")
    default:
        print("\(point) is outside of the box")
    }
}

switch with tuple


whereIs((0, 0))     // (0, 0) is at the origin
whereIs((3, 0))     // (3, 0) is on the x-axis
whereIs((1, 2))     // (1, 2) is inside the box
whereIs((3, 2))     // (3, 2) is outside of the box

6. Value Bindings

Swift λŠ” switchκ΅¬λ¬Έμ—μ„œλ„ Value Bindingsλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

func anotherPoint(_ point: (Int, Int)) {
    switch point {
    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))")
    }
}
anotherPoint((4, 0))    // on the x-axis with an x value of 4
anotherPoint((0, 2))    // on the y-axis with a y value of 2
anotherPoint((2, 6))    // somewhere else at (2, 6)

7. Where

Value Bindings 에 whereλ₯Ό μ΄μš©ν•΄ μΆ”κ°€ 쑰건을 κ±Έ 수 μžˆλ‹€.

func yetAnotherPoint(_ point: (Int, Int)) {
    switch point {
    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")
    }
}

μœ„ ν•¨μˆ˜λ₯Ό ν’€μ–΄μ“°λ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

func yetAnotherPoint(_ point: (Int, Int)) {
    let (x, y) = point
    switch true {
    case x == y:
        print("(\(x), \(y)) is on the line x == y")
    case x == -y:
        print("(\(x), \(y)) is on the line x == -y")
    default:
        print("(\(x), \(y)) is just some arbitrary point")
    }
}

Switch case value bindings with where


yetAnotherPoint((4, 4))     // (4, 4) is on the line x == y
yetAnotherPoint((3, -3))    // (3, -3) is on the line x == -y
yetAnotherPoint((3, 7))     // (3, 7) is just some arbitrary point

단, whereλŠ” λ‹¨λ…μœΌλ‘œ μ‚¬μš©λ  수 μ—†κ³  case 에 Value Bindingsκ°€ 된 μƒμˆ˜λ‚˜ λ³€μˆ˜κ°€ μžˆμ–΄μ•Όν•œλ‹€.

8. Compound Cases

μœ„ No Implicit Fallthrough μ—μ„œ λ³Έ κ²ƒμ²˜λŸΌ Swift 의 switch λŠ” multiple case matchλ₯Ό μ§€μ›ν•˜λ―€λ‘œ μ—¬λŸ¬ μΌ€μ΄μŠ€λ₯Ό ν˜Όν•©ν•΄μ„œ Compound Casesλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

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) is not a vowel or a consonant")
}

// e is a vowel


Compound Cases μ—μ„œ Value Bindings λ₯Ό μ‚¬μš©ν•˜λŠ” 것 μ—­μ‹œ κ°€λŠ₯ν•˜λ‹€.

func stillAnotherPoint(_ point: (Int, Int)) {
    switch point {
    case (let distance, 0), (0, let distance):
        print("On an axis, \(distance) from the origin")
    default:
        print("Not on an axis")
    }
}

// On an axis, 9 from the origin


λ§ˆμ°¬κ°€μ§€λ‘œ μœ„ Switch-True λ₯Ό μ‚¬μš©ν•œ Validation Checkλ₯Ό λ‹€μ‹œ μ“°λ©΄ λ‹€μŒκ³Ό 같이 μ‚¬μš©ν•  μˆ˜λ„ μžˆλ‹€.

struct User {
    var name: String?
    var age: Int?
    var phone: String?
    var height: Double?
    var weight: Double?
}

func validateUserWithCompoundCases(of user: User?) -> Bool {
    guard let user = user else { return false }
    
    switch true {
    case user.age == nil, user.name == nil,
        user.phone == nil, user.height == nil,
        user.weight == nil
        : print("Something is nil"); return false
    case (user.age! < 0) || (user.age! > 130): print("invalid age"); return false
    default: return true
    }
}

print("Validation check result is \(anotherResult!).")
invalid age
Validation check result is false.

5. Control Transfer Statements πŸ‘©β€πŸ’»

Swift μ—λŠ” μ½”λ“œμ˜ 흐름을 μ œμ–΄ν•˜λŠ” 5가지 Control Transfer Statementsκ°€ μžˆλ‹€.

  • continue
  • break
  • fallthrough
  • return
  • throw

1. continue

iteration의 ν˜„μž¬ loop λ₯Ό μ€‘λ‹¨ν•˜κ³  λ‹€μŒ 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)     // grtmndsthnklk

continue 에 μ˜ν•΄ λͺ¨μŒμ΄λ‚˜ 곡백을 λ§Œλ‚˜λ©΄ κ±΄λ„ˆλ›°κ³  자음만 좜λ ₯ν•œλ‹€.

2. break

iteration loop λ˜λŠ” switch의 전체 ꡬ문을 μ¦‰μ‹œ μ€‘λ‹¨ν•˜κ³  νƒˆμΆœν•œλ‹€.

  • Iteration
let puzzleInput = "great minds think alike"
var puzzleOutput = ""
let charactersToRemove: [Character] = ["a", "e", "i", "o", "u", " "]
for character in puzzleInput {
    if charactersToRemove.contains(character) {
        break
    }
    puzzleOutput.append(character)
}
print(puzzleOutput)     // gr
  • Switch
let someLetter = "B"

switch someLetter {
case "A": print("This character is 'A'.")
case "B": break
case "C": print("This character is 'C'.")
default: break
}

Swift 의 Switch 문은 기본적으둜 No Implicit Fallthroughμ΄λ―€λ‘œ breakλŠ” μƒλž΅ν•΄λ„ λœλ‹€.

3. fallthrough

Switchμ—μ„œ λ§€μΉ­λ˜λŠ” case 의 λ‹€μŒ caseλ₯Ό μ‹€ν–‰ν•˜λ„λ‘ μ˜λ„μ μœΌλ‘œ λͺ…λ Ήν•œλ‹€.

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)  // The number 5 is a prime number, and also an integer.

Swift 의 Switch 문은 case λ§€μΉ­μ‹œ breakκ°€ κΈ°λ³Έ μž‘λ™ μˆœμ„œμ΄λ―€λ‘œ λ‹€λ₯Έ 언어와 달리 fallthroughκ°€ ν•„μš”ν•  경우 λͺ…μ‹œν•΄μ•Όν•œλ‹€.

4. return

breakκ°€ iteration loop λ˜λŠ” switch 의 전체 ꡬ문을 μ¦‰μ‹œ μ€‘λ‹¨ν•˜κ³  νƒˆμΆœ ν•˜λŠ” κ²ƒμ²˜λŸΌ return은 function λ‚΄λΆ€μ—μ„œ μ‚¬μš©λ˜μ–΄ 전체 ꡬ문을 μ¦‰μ‹œ μ€‘λ‹¨ν•˜κ³  값을 λ°˜ν™˜ν•œλ‹€.

λ”°λΌμ„œ return이 μ‹€ν–‰λ˜λ©΄ function λ‚΄λΆ€ 의 iteration loop λ˜λŠ” switch ꡬ문은 더 μƒμœ„ scope 인 function μžμ²΄κ°€ μ’…λ£Œλ˜λ―€λ‘œ, λ³„λ„μ˜ break 없이도 μ€‘λ‹¨λœλ‹€.

5. throw

throwλŠ” returnκ³Ό λ§ˆμ°¬κ°€μ§€λ‘œ function λ‚΄λΆ€μ—μ„œ μ‚¬μš©λ˜μ–΄ 전체 ꡬ문을 μ¦‰μ‹œ μ€‘λ‹¨ν•˜κ³ , Error λ˜λŠ” fatalErrorλ₯Ό λ°˜ν™˜ν•œλ‹€.

6. Labeled Statements

iteration loopλ‚˜ switch와 같은 ꡬ문을 쀑볡해 μ‚¬μš©ν•  수 μžˆλ‹€. 이 λ•Œ 둜직의 흐름을 μ •ν™•νžˆ μ œμ–΄ν•˜κΈ° μœ„ν•΄ label이 ν•„μš”ν•˜κ³ , 이λ₯Ό labeld statements라 ν•œλ‹€.

Syntax

label name: while condition {
    statements
}


μ£Όμ‚¬μœ„ 1 이 μ£Όμ‚¬μœ„ 2 보닀 값이 크면 κ²Œμž„μ„ μ’…λ£Œν•˜λŠ” loop λ₯Ό λ§Œλ“ λ‹€.

func rollDice() -> Int {
    Int.random(in: 1...6)
}
for _ in 1...10 {
    let dice1: Int = rollDice()
    let dice2: Int = rollDice()
    
    print("Without label >> dice1: \(dice1), dice2: \(dice2), therefore dice1 > dice2 is \(dice1 > dice2)")
    
    switch true {
    case dice1 > dice2: break
    default: continue
    }
}
Whitout label >> dice1: 1, dice2: 4, therefore dice1 > dice2 is false
Whitout label >> dice1: 2, dice2: 4, therefore dice1 > dice2 is false
Whitout label >> dice1: 3, dice2: 3, therefore dice1 > dice2 is false
Whitout label >> dice1: 1, dice2: 1, therefore dice1 > dice2 is false
Whitout label >> dice1: 3, dice2: 4, therefore dice1 > dice2 is false
Whitout label >> dice1: 4, dice2: 6, therefore dice1 > dice2 is false
Whitout label >> dice1: 6, dice2: 2, therefore dice1 > dice2 is true
Whitout label >> dice1: 3, dice2: 1, therefore dice1 > dice2 is true
Whitout label >> dice1: 6, dice2: 6, therefore dice1 > dice2 is false
Whitout label >> dice1: 3, dice2: 4, therefore dice1 > dice2 is false

break에 μ˜ν•΄ For-In Loops λ₯Ό μ’…λ£Œν•  것 κ°™μ§€λ§Œ switch ꡬ문 μ•ˆμ—μ„œ λ°œμƒν•œ break 이기 λ•Œλ¬Έμ— switch ꡬ문만 μ’…λ£Œ ν•œλ‹€.
λ”°λΌμ„œ λ‹€μŒκ³Ό 같이 label을 μ΄μš©ν•˜λ©΄ μ œμ–΄ λͺ…령을 μ •ν™•νžˆ 컨트둀 ν•  수 μžˆλ‹€.

gameLoop: while true {
    let dice1: Int = rollDice()
    let dice2: Int = rollDice()
    
    print("With label >> dice1: \(dice1), dice2: \(dice2), therefore dice1 > dice2 is \(dice1 > dice2)")
    
    switch true {
    case dice1 > dice2: break gameLoop
    default: continue
    }
}
With label >> dice1: 2, dice2: 5, therefore dice1 > dice2 is false
With label >> dice1: 4, dice2: 1, therefore dice1 > dice2 is true

7. Early Exit

guardλŠ” if 와 μœ μ‚¬ν•˜μ§€λ§Œ 항상 else 절이 λ’€λ”°λ₯΄λ©°, else clause λŠ” λ°˜λ“œμ‹œ return, break, continue, throw와 같은 Control Transfer Statementsλ₯Ό μˆ˜ν–‰ν•˜κ±°λ‚˜ fatalError(_:file:line:)와 같이 return이 μ—†λŠ” ν•¨μˆ˜λ‚˜ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•΄μ•Όν•œλ‹€.


μœ„ Switch-True λ₯Ό μ‚¬μš©ν•œ Validation Check, Validation Check with Compound Cases guardλ₯Ό μ΄μš©ν•΄ λ‹€μ‹œ 써보자.

struct User {
    var name: String?
    var age: Int?
    var phone: String?
    var height: Double?
    var weight: Double?
}

func validateUser(of user: User?) -> Bool {
    guard let user = user else { return false }
    
    guard let age = user.age else { print("age is nil"); return false }
    if (age < 0) || (age > 130) { print("invalid age"); return false }
    guard let _ = user.name else { print("name is nil"); return false }
    guard let _ = user.phone else { print("phone is nil"); return false }
    guard let _ = user.height else { print("height is nil"); return false }
    guard let _ = user.weight else { print("weight is nil"); return false }
    return true
}


var myUser = User(name: "홍길동", age: 132, phone: "010-4434-3556", height: 183.2, weight: 74)

let result: Bool? = validateUser(of: myUser)
print("Validation check result of myUser is \(result!).")
invalid age
Validation check result of myUser is false.


var myUser = User(name: "μž₯보고", age: 42, phone: "010-2342-1234", height: 175.2, weight: nil)

let result: Bool? = validateUser(of: myUser)
print("Validation check result of myUser is \(result!).")
weight is nil
Validation check result of myUser is false.


var myUser = User(name: "μ΄μˆœμ‹ ", age: 30, phone: "010-7423-3464", height: 169.6, weight: 52)

let result: Bool? = validateUser(of: myUser)
print("Validation check result of myUser is \(result!).")
Validation check result of myUser is true.




Reference

  1. β€œControl Flow.” The Swift Programming Language Swift 5.7. accessed Oct. 11, 2022, Swift Docs Chapter 4 - Control Flow.