상세 컨텐츠

본문 제목

[swift] Guard let

SWIFT

by 옹홍 2021. 3. 29. 21:30

본문

Swift - Guard let

Control Flow 중에 하나, Optional Binding에 많이 사용되는 문이라고 한다. 

// guard let
func greet(person: [String: String]){
    guard let name = person["name"] else {
        return
    }
    print("Hello \(name)")
    guard let location = person["location"] else {
        return
    }
    print("Hello \(location)")
    
    if let name = person["name"]{
        
    } else {
        
    }
}

greet(person: ["name": "Johnn", "location": "seoul"])

 

이렇게 guard 구문으로 control flow가 가능하다. 위에서 구조체에 name이라는 key의 value 값이 존재한다면? guard let 아래문으로 내려가게 된다. 마찬가지로 location이라는 key의 value 값이 존재한다면? guard let 아래 문으로 내려가게 되는 것이다.

Guard let을 사용한 optional Binding

if let을 사용한 optional Binding, guard let을 사용한 optional Binding

func fullName(name: String, rawPrefix: String?){
			//if let
      if let prefix = rawPrefix {
          print(prefix+name)
      } else {
          print("prefix need")
      }
    //guard let
    guard let prefix = rawPrefix else {
        print("prefix need")
        return
    }
    print(prefix+name)
}
fullName(name: "dohyun", rawPrefix: "chung")
fullName(name: "dohyun", rawPrefix: nil)

출력 

chungdohyun ( if let)

chungdohyun (guard)

prefix need ( if let)

prefix need (guard)

Guard let의 특징

  1. guard let은 guard let 뒤에 따라 붙는 코드의 실행 결과가 true일때 코드를 진행한다. if 문과 다르게 guard 구문은 항상 else 구문이 뒤에 따라와야한다
  2. guard 뒤에 따라오는 bool 값이 false면 else블록 실행하고, 상위 블록코드를종료하는 return, break continue, throw가 필요하다. 하지만 return break continue throw 등을 사용 못하면 불가능하다. -> 함수, 메서드, 반복문 내에서 사용이 용이하다.
  3. 보통 예외사항만을 처리하고 싶다면 guard 구문을 사용하는 것이 편하다.
  4. guard let의 새로 생긴 변수는 guardlet 이후의 상위 블록에서 지역 상수처럼 사용가능하다. if let의 경우는 {} 안에서만 변수를 사용해야한다는 단점이 존재한다.
  5. guard let으로 옵셔널 바인딩을 할 때, 여러 개를 같이할 수 있다는 장점이 있다.'

Loop빠져나오기

func guardControlFlow() {
    let strings: [String] = ["hi", "dohyun", "findout", "guardlet"]
    for string in strings{
        guard string != "guardlet" else {
            continue
            // string이 guardlet일때는 아래 수행 아니면 걍 다 재끼고 다시 포문 돌리기
        }
        print(string)
    }
}
guardControlFlow()

Error Throw

enum VendingMachineError: Error {
    case invalidSelection
    case insufficientFunds(coinsNeeded: Int)
    case outOfStock
}

struct Item{
    var price: Int
    var count: Int
}

class VendingMachine{
    var inventory = [
        "Candy Bar" : Item(price:12, count: 7),
        "Chips" : Item(price: 10 , count: 4),
        "Pretzels": Item(price: 7, count: 11)
    ]
    var coinDeposited = 0
    
    func vend(itemNamed name: String) throws {
        guard let item = inventory[name] else {
            throw VendingMachineError.invalidSelection
        }
        guard item.count > 0 else {
            throw VendingMachineError.outOfStock
        }
        guard item.price <= coinDeposited else {
            throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinDeposited)
        }
    }
}

Guard let 이후 지역상수

func guardletF (string: String?){
    guard let string = string else {
        return
    }
    print("string is \(string)")
}
guardletF(string: "test")

여러개의 Optional Binding

func manyGuardLet(first: String?, second: String?, third: String?){
    guard let first = first, let second = second, let third = third else {
        return
    }
    print("first is \(first), second is \(second), third \(third)")
}
manyGuardLet(first: "one", second: "two", third: "three") // one two three
manyGuardLet(first: nil, second: "two", third: "three") // X
manyGuardLet(first: "one", second: nil, third: "three") // X
manyGuardLet(first: "one", second: "two", third: nil) // X

관련글 더보기

댓글 영역