안녕하세요~~ 오늘은 오랜만에 스위프트 문법을 공부했습니다. 저번에 배웠던 Optional에서 좀 더 심화되는 내용입니다. 옵셔널 바인딩이란 옵셔널된 변수나 상수를 안전하게 unwrapping하는 방법입니다. 저번에 배웠던 강제 언래핑(!)은 nil값을 가질 때 오류가 나서 위험한 방법이라고 했었는데 그것의 해결방법이 옵셔널 바인딩입니다. 그럼 더 자세하게 알아보죠!
옵셔널 바인딩이란 강제로 옵셔널을 여는 방식(Force unwrapping)이 아닌 안전하게 확인을 해보고 unwrapping하는 방법입니다. 즉, if문을 이용하여 옵셔널에 할당된 값을 임시 변수 또는 상수에 할당을 해주는 방식입니다.
Force unwrapping : !를 써서 강제로 옵셔널 추출
Optional Binding : if let, guard let을 써서 옵셔널 추출
if let 또는 if var을 사용하여 옵셔널의 값이 존재하는지를 검사한 뒤, 존재한다면 그 값을 다른 변수에 대입시켜줍니다. 만약 옵셔널에 값이 있다면 if문 안으로 들어가게 되고 nil이라면 그냥 통과하게 되는 방식이죠!! 이렇게 확인을 해주고 unwrapping을 해준다면 강제로 unwrapping해주는 것보다 훨씬 안전할 것입니다.
그럼 playground에서 간단한 코드를 짜서 이해를 해보겠습니다.
let x : Int? = 10
let y : Int? = nil
if let xx = x {
print("x = \(xx)")
}
else {
print("x is Optional")
}
if let yy = y {
print("y = \(yy)")
}
옵셔널 상수 x와 옵셔널 상수 y에 각각 10과 nil로 초기화를 해주었습니다. 강제 언래핑을 해서 x!, y!로 코드를 작성한다면 y!에는 오류가 생길겁니다. 하지만 옵셔널 바인딩을 사용해서 위 코드와 같이 쓴다면 값이 있는 x는 xx에 대입이 되서 if문을 수행하게 되고 값이 nil인 y는 yy에 대입하지 못하고 그냥 통과하게 될 겁니다.
결과도 잘 나왔군요! 이렇게 강제로 unwrapping하는 것보다 옵셔널 바인딩을 사용 하게 되면 안전하게 unwrapping을 할 수 있습니다.
옵셔널 바인딩을 할때는 여러 변수나 상수 또한 같이 할 수 있는데 이들을 ,(콤마)로 구분지어서 사용한답니다.
let name1 : String?
let name2 : String?
name1 = "Song"
name2 = "Kim"
if let nameFirst = name1,
let nameSecond = name2 {
print(nameFirst, nameSecond)
}
다음과 같이 문자열 옵셔널 상수 두개를 선언한 후 옵셔널 바인딩을 이용해 unwrapping을 해주었습니다. 이때 ,(콤마)를 이용해서 한번에 두 상수를 unwrapping을 해준것을 확인할 수 있었습니다.
옵셔널 바인딩을 할 때 if let 뿐만 아니라 guard let이라는 것도 많이 쓰입니다. 둘은 거의 비슷하지만 약간의 차이가 있습니다. 일단은 코드를 써보면서 guard let을 이해해 보겠습니다.
let x : Int? = 10
let y : Int? = nil
func opbinding() {
guard let xx = x else {
return print("x is Optional")
}
print(xx)
guard let yy = y else {
return print("y is Optional")
}
print(yy)
}
opbinding()
위와 비슷한 코드를 하나 짰습니다. 옵셔널 상수 x와 옵셔널 상수 y에 각각 10과 nil로 초기화 해주고 이번에는 guard let을 써서 옵셔널을 추출했습니다. if let과 구문은 비슷하지만 guard let에서는 else인 부분만 작성이 가능합니다. 즉, 값이 nil이여서 옵셔널 추출이 되지 않을때만 어떠한 행동을 취할 수 있죠. 그리고 만약 nil값이 아닐 걸 확인하고 옵셔널을 성공적으로 추출했다면 guard let문을 통과하게 되게 되는 거죠! 여기서 한가지 중요한 점이 있었는데 이렇게 guard let문을 통과하게 되면 저장된 상수는 전역변수로써 사용이 가능하다는 점입니다! 훨씬 편하게 사용할 수 있겠군요!!
guard let의 else문 안에는 항상 return 아니면 throw문이 와야 합니다. 여기서 throw문은 예외처리문으로 나중에 제대로 공부를 해보도록 하죠! 위 코드에서는 함수안에 guard let문이 있으므로 return을 썼습니다.
설명이 조금 길어졌네요. 바로 실행을 해보겠습니다.
결과를 보면 x값은 guard let을 통과해서 잘 프린트 되었고, y값은 nil이므로 else문으로 빠져 "y is Optional"이 반환된 것을 확인할 수 있습니다.
*지역변수, 전역변수
둘은 Optional Binding에서 대표적으로 사용되는 구문입니다. 하지만 미세한 차이가 있었는데요, 어떤 차이인지 확인을 해보겠습니다.
guard let yy = y else {
return print("y is Optional")
}
print(yy)
guard let은 위 코드와 같이 옵셔널 추출을 실패하여 false가 된 else문만 제어를 할 수 있습니다. 그리고 guard let은 상수안에 옵셔널 값을 할당한다면 위 코드처럼 전역변수로써 사용을 할 수 있습니다. 즉, guard let문 밖에서도 할당 상수를 자유롭게 사용이 가능하다는 것이죠.
if let xx = x {
//xx는 여기서만 사용가능
}
else {
print("x is Optional")
}
print(xx) //error!
if let의 경우에는 옵셔널 추출을 실패하여 false가 된 else문 뿐만 아니라 성공한 경우에도 제어를 할 수 있습니다. 하지만 할당 상수를 if문 안에서만 사용할 수 있습니다. 위의 코드처럼 실행을 해본다면 xx는 지역변수이기 때문에 오류가 발생하게 됩니다.
오늘은 옵셔널 바인딩에 대해 공부를 해보았습니다. 강제로 추출하는 방식보다는 훨씬 안전한 방법이기 때문에 꼭 이렇게 옵셔널 바인딩으로 옵셔널을 추출해야겠네요. 그럼 오늘 하루도 수고 많으셨습니다~
guard let에서 새로 생긴 변수는 전역변수가 아니고 guard let 문장 밖에서 사용가능한 지역변수입니다.