IT/IPhone개발

[Swift] Optional 사용

차가운남자 2016. 5. 4. 11:22

코딩을 하다가 String 을 Int형으로 변환을 하려고 했는데

var str = String()

var Int value: Int = 0

value = Int(str)

이렇게 하니 에러가 발생하였다. 그래서 xcode에서 !를 넣으라고 하니깐 되었다. 그래서 다른 블로그를 찾다가 잘정리된것이 있어서 공유하고자 퍼왔습니다.

오늘은 첫번째 시간으로 Swift의 Optionals에 대해 배워보겠습니다.

Optionals는 보통의 Int나 String처럼 값(value)을 나타낼 뿐만이 아니라, 값(value)이 없음을 나타낼 수도 있는 Swift가 제공하는 특별한 타입(type)입니다.

그럼 왜 값이 없을수도 있는 것일까요?

예를들어 아래처럼 사람에 대해 정의한다고 해 보겠습니다.

var name: String = "keicoder"  
var age: Int = 45  
var occupation: String = "Software Developer"

name과 age는 모든 사람이 가지고 있지만, 직업은 모든 사람이 가지고 있는건 아니죠(무직을 직업으로 치지 않으면요 –;).

혹은 직업을 가지고 있었더라도 직장에서 해고가 되거나, 복권에 걸려 자의적으로 일을 그만둘 수도 있을겁니다(ㅋ 정말 이렇게 되면 좋겠네요 :)).

물론 직업을 공란(empty string)으로 둘 수도 있겠지만, 값이 없는 상태(nil)로 두는것도 방법일 것입니다. 이럴때 optionals가 유용한 방법이겠네요.

Optionals 선언

Optionals를 그냥 네모난 박스라고 가정해 보겠습니다. 이 박스에는 무엇이든 담을 수 있지만 동시에 아무것도 담기지 않을수(nil)도 있습니다. 물론 값이 담겨있던 담기지 않았던 간에 박스는 항상 있습니다. 반면 String, Int 등은 항상 값이 있으며, 박스가 없는 상태이지요.

Optionals를 선언하는 방법은 아래와 같습니다.

var name: String?  
name = "keicoder"

혹은 아래와 같이 nil을 지정할 수 있습니다.

name = nil

다시한번 말씀드리지만 name이라는 박스는 항상 있습니다. 그 박스에 “keicoder”라는 이름(값)을 넣을수도 혹은 박스를 비울수도 있는 것이지요.

Optionals에서 값을 가져오는 방법

let age: Int? = 30
print(age)

위 코드는 Log 콘솔창에 아래의 메시지를 보여줍니다.

Optional(30)

만약 위 코드를 아래와 같이 수정하면 어떻게 될까요?

print(age + 1)

아래와 같은 에러 메시지가 출력됩니다.

error: value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?

위 에러 메시지에서 보듯 Optinals 안에 있는 값을 이용하기 위해선 Optinals를 풀어낼(unwrapped) 필요가 있습니다 (Optinals는 단순한 값이 아니라 box라는 점을 기억하세요).

FORCE UNWRAPPING

var name: String? = "keicoder"

Optionals를 풀어내는 방법은 크게 두가지가 있습니다. 그 중 첫번째가 ‘force unwrapping’입니다.

var unwrappedName = name!
print("Name is \(unwrappedName)")

name 변수 마지막에 느낌표(!)가 컴파일러(compiler)에게 Optinals안의 값을 강제로 풀어달라고 합니다. 결과는 다음과 같습니다.

Name is keicoder

하지만 이 방식은 주의할 필요가 있습니다. 만약 Optinals의 값이 nil이면 아래와 같이 runtime 에러가 발생하여 프로그램이 죽게 되니까요.

fatal error: unexpectedly found nil while unwrapping an Optional value

그럼 어떻게 Optionals를 안전하게 풀 수 있을까요?

아래와 같이 if 문을 쓸 수 있습니다.

if name != nil {
   var unwrappedName = name!
   print("Name is \(unwrappedName)")
} else {
   print("Name is \(name)")
}

하지만 이렇게 Optinals를 푸는건 어딘가 지루한 면이 있군요. 다행히 Swift는 ‘If let’ 바인딩(binding) 이라는 방법으로 Optinals 안의 값에 안전하게 접근하는 방법을 제공해 줍니다.

IF LET 바인딩(BINDING)

if let unwrappedName = name {
   print("Name is \(unwrappedName)")
} else {
   print("Name is \(name)")
}

눈치가 빠른 분들은 아마 느낌표(!)가 사라진 것을 아실텐데요. 만약 name 변수에 값이 있다면 unwrappedName 변수는 Optinals를 풀어낸 값을 가지게 됩니다. name 변수가 nil이라면 else 구문이 실행되고 unwrappedName 변수는 아예 존재하지도 않게 됩니다.

여기까지 보신 분들은 이제 ’If let’ 바인딩 방식이 ‘Force unwrapping’ 방식보다 훨씬 안전하다는 점을 아셨을 겁니다.

NIL 합치기(COALESCING)

마지막으로 Optinals를 푸는 방법이 하나 더 있습니다. nil 합치기(coalescing)라 불리는 방법으로 사용법은 아래와 같습니다.

var optionalInt: Int? = 22
var value = optionalInt ?? 0

Nil 합치기(coalescing)는 위 코드의 두번째 라인 더블 물음표(??)를 의미합니다. 만약 optionalInt가 nil이면 0가, 값이 있다면 그 값을 value에 넘겨주게 됩니다.

위 코드는 아래의 코드와 동일합니다.

var optionalInt: Int? = 22
var value: Int
if let unwrapped = optionalInt {
   value = unwrapped
} else {
   value = 0
}

만약 위 코드의 optionalInt의 값을 nil로 바꾸면

optionalInt = nil

value 값은 0가 되겠죠.:)

키 포인트

  • Nil은 값이 없음을 뜻합니다.
  • Optional이 아닌 변수(var)나 상수(let)는 항상 non-nil 값을 가집니다.
  • Optinal 변수나 상수는 값을 가지고 있거나 혹은 없는(nil), 일종의 상자(box)와 같습니다.
  • Optional 안의 값을 사용하려면 먼저 풀어야(unwrap) 합니다.
  • Optional 안의 값을 안전하게 푸는(unwrap) 방법은 ‘if let’ 바인딩, ‘nil 합치기(coalescing)’가 있습니다.
  • 강제로 푸는(forced unwrapping) 방법이 있으나, 만약 optional의 값이 nil 이면 runtime 에러가 발생하기 때문에 가급적 사용을 자제하는게 바람직합니다.


'IT > IPhone개발' 카테고리의 다른 글

[Swift] IOS 화면 고정하기  (0) 2016.05.19
[Swift] 애드몹 IOS 연동하기  (0) 2016.05.19
[Swift] Segue로 값넘기기  (0) 2016.05.03
[Swift] UIAlertView 바뀐 사용법  (0) 2016.05.02
[Swift] xcode 7.3 Swift 2.2 변경된 것들  (0) 2016.04.27