티스토리 뷰

Swift

옵셔널(Optional) 정복하기 - 3장

swallow.iOS 2022. 5. 9. 19:47

안녕하세요! Swallow입니다!

이번 포스팅은 지난번에 말씀드렸던

옵셔널을 우아하고 더 안전하게 벗겨낼 수 있는

⭐️ 옵셔널 바인딩 ⭐️

관한 글입니다!

항상 어떠한 조언, 충고 환영입니다!

시작하기에 앞서 이 글은

앨런 Swift 문법 마스터 스쿨 강의와 야곰님의 스위프트 프로그래밍 책

공부하고 참고하여 작성하였습니다!

그럼 시작하겠습니다!

 

 

저번 글에서도 말씀드렸다시피

옵셔널 타입의 값을 사용하기 위해서는

옵셔널을 포장지를 벗겨낸 후

사용이 가능하다고 말씀드렸습니다!

 

그럼 오늘 배울

⭐️ 옵셔널 바인딩 ⭐️

과연 이게 무엇일까요?

 

옵셔널 바인딩이란?

쉽게 이야기하자면

새로운 상수 또는 변수에 할당(바인딩) 되는 경우에만

작업을 실행하겠다 라는 의미입니다!

 

어떨 때는 바인딩이 되고 어떨 때는 안될까라고 생각을 해보면

값이 존재한다면 바인딩이 되고

nil이 존재하면 바인딩이 되질 않습니다!

꼭 기억해 두세요!

 

그리고 옵셔널 바인딩은 크게

두 가지 방법으로 사용이 됩니다

 

첫 번째

if let 바인딩

if문을 사용해서 바인딩이 되는 경우 옵셔널을 벗겨내는 방법입니다!

말 보단 역시 예시로 보여드리게 좋겠죠?

var str: String? = "잘 부탁드립니다"
print(str)  // Optional("잘 부탁드립니다")


if let hello = str {  // hello 라는 상수에 바인딩이 된다면
    print(hello)      // 옵셔널을 벗겨내고 출력
}

 

제가 설명을 해드리자면

변수 str이 String? 타입이고 "잘 부탁드립니다"라는 값이 존재합니다!

그 상태로 출력을 한다면,

당연히 Optional("잘 부탁드립니다")가 출력이 되겠죠?

 

근데 저희는 Optional("잘 부탁드립니다")가 아닌!!!

잘 부탁드립니다 를 출력하고 싶은 경우라서

if let 바인딩을 사용한 것입니다!

 

그래서 새로운 상수인 hello에 str이 바인딩이 된다면

즉, str에 값이 존재해서 할당이 된다면

print(hello)을 한 것입니다!

 

만일 nil이 존재했더라면,

바인딩이 되질 않았기에

당연히 print(hello)가 실행이 되질 않았겠죠?

 

추가적인 작업까지 원하신다면

else문을 추가해서 사용하시면 됩니다!

 

어때요? 설명을 들으니 더 이해되시죠? 😁

 

두 번째

guard let 바인딩

guard문을 사용해서 바인딩이 되는 경우 옵셔널을 벗겨내는 방법입니다!

guard문 같은 경우 함수(메서드) 내부에서 쓰이고,

조건을 만족하지 못한다면

바로 else문을 통해 해당 함수(메서드)를 종료(return) 시킵니다!

 

쉽게 말씀드리면

guard문 조건을 만족 못하면 내 함수에서 당장 나가거라!

라는 의미입니다

그래서 guard문은 else문을 먼저 배치해서 조건을 판별하여 조기종료를 시키는 역할입니다!

 

 

그럼 바로 예시를 한번 보실까요?

func doSomething(name: String?) {  // 파라미터로 받는 타입을 String? 타입으로 정의
    guard let myName = name else { return }  // myName에 name이 바인딩 되면 print(myName) 실행
    print(myName)
}

doSomething(name: "swallow")

func doSomething(name: String?) {  // 위의 코드와 동일합니다
    guard let myName = name else { // 단순히 else 구문의 return을 앞으로 당겼냐 안당겼냐의 차이 입니다
        return
    }
    print(myName)
}

추가 설명드리겠습니다!

우선 위에서 말씀드렸다시피 guard문은 함수(메서드) 내부에서 쓰인다고 말씀드렸죠?

그리고 위의 예시에서는 파라미터로 받는 타입을 String?으로 정의를 해주었습니다!

그리고 함수 실행 시 "swallow"를 파라미터로 전달하고 있습니다!

 

이제 guard문을 분석해보자면

새로운 상수 myName에 파라미터인 name이 바인딩이 된다면 else문을 지나치고

print(myName)을 해라 라는 의미입니다!

 

그런데!!!!

myName에 name이 바인딩이 되질 않는다면 else문을 통해서 바로 return

즉, 해당 함수를 종료시킨다 라는 의미입니다!

 

guard문 같은 경우 쉽게 생각하자면

⭐️ if문에서 else문을 먼저 앞으로 뺀 경우라고 생각하시면 좋을 거 같습니다 ⭐️

 

그런데 여기서 if let 바인딩과 guard let 바인딩의 차이가 보이시나요?

바로 새로운 상수의 범위(scope)의 차이입니다!

 

if let 바인딩의 경우

새로운 상수인 hello의 범위(scope)가 if문 내부입니다

즉, if문 내부에서만 사용이 가능합니다

var str: String? = "잘 부탁드립니다"
print(str)  // Optional("잘 부탁드립니다")


if let hello = str {  // hello 라는 상수에 바인딩이 된다면
    print(hello)      // 옵셔널을 벗겨내고 출력
}

아래 예시처럼 if문 밖에서 hello에 접근을 하면

에러가 발생합니다! 😱

var str: String? = "잘 부탁드립니다"
print(str)  // Optional("잘 부탁드립니다")


if let hello = str {  // hello 라는 상수에 바인딩이 된다면
    print(hello)      // 옵셔널을 벗겨내고 출력
}

print(hello)  // 에러

 

그런데 guard let 바인딩은 좀 다릅니다!

guard let 바인딩의 경우

새로운 상수인 myName의 범위가 guard문 밖입니다!

그래서 myName을 else문 내부에서 사용이 불가능합니다!

주의하셔야 합니다!!

외워두시면 좋은 부분이에요!

func doSomething(name: String?) {
    guard let myName = name else {
        print(myName)              // 상수 myName이 해당 범위가 아니기에 에러!!!
        return
    }
    print(myName)                  // 상수 myName이 guard문 밖의 범위가 맞기에, OK!
}
doSomething(name: "swallow")

 

 

마지막으로 알려드릴 부분이 있습니다! 😁

if let, guard let만 가능한 걸까?

if var, guard var는 사용 못하는 건가?

라는 생각하실 수 있어요!

물론!!

둘 다 사용이 가능합니다!

어느 것을 사용하든 상관이 없습니다!

 

그런데 일반적으로 사용하지 않는 이유가 있습니다!

왜냐하면 논리적으로 생각을 해보면

값을 벗기면, 그 값을 바로 사용을 합니다

그 값을 바꾸는 경우가 잘 없어요!

그래서 if var, guard var를 잘 사용을 하지 않습니다!

 

옵셔널 바인딩 쉽게 보는 그림 한장정리!

조금이나마 재밌게 보시라고, 그렸습니다! ㅎ

 

이번 포스팅에서는 Optional Unwrapped 방법 중

옵셔널 바인딩에 대해서 알아보았는데요!

제 글을 읽으시고 조금이라도 답답한 부분이

해결되셨길 바랍니다!

다음 포스팅에서는 Optional Unwrapped 방법에서 기본값을 제공할 수 있는

⭐️ 닐 코얼레싱(Nil-Coalescing) ⭐️

알아보겠습니다!

 

감사합니다!

항상 어떠한 피드백 환영입니다☺️

 

댓글