티스토리 뷰

Swift

[Swift] Optionals (옵셔널)

learner._.Kio 2021. 2. 18. 00:41

목차

  • Optionals (옵셔널)
    • Optionals (옵셔널)
    • Unwrapping (언래핑)
    • Forced Unwrapping! (강제추출!)
    • Optional 특징
  • Optional Binding (옵셔널 바인딩)
    • If let / while let / guard let
  • Implicitly Unwrapped Optionals (IUO, 암시적 추출 옵셔널!)
  • Nil-Coalescing Operator (Nil 병합 연산자, ??)




Optionals (옵셔널)

Optionals은 값이 없다는 뜻으로 nil로 표기한다.

Optionals 선언 및 예시

let optionalNum: Int? = nil
// 자료형 뒤에 공백없이 '?'을 붙이면 옵셔널이 된다.

let optionalNum = nil // error
// nil 자체로는 추론할 형식이 없기 때문에 타입을 지정해야 한다.
let str: String = "Swift"
// Non-optional Type
let opionalStr: String? = nil
// Optinal Type

let a: Int? = nil
let b = a    // a가 optionals int라면 b도 optionals int

Unwrapping (언래핑)

var num: Int? = 123
let n = 123

print(num)            // Optional(123) // Unwrapping == 값에 랩이 씌워져있는 느낌
print(n)                // 123

Forced Unwrapping (포스언래핑, 강제추출)

var num: Int? = 123
print(num!)                    // 123

num = nil
print(num!)                    // error
/* 
error - 값이 없는데 강제추출할 수 없다.
Forced Unwrapping으로 추출할 때는 값이 먼저 있는지 확인해야 한다. 
*/

if num != nil {
      print(num!)
}
// if문으로 값 확인하여 추출하면 안전하게 확인가능하다.

Optional 특징

  • optional에 저장되어 있는 값을 사용하려면 값을 unwrapping 해야한다.

  • nil이 있는 상태에서 강제추출하면 crash가 발생한다.

  • optional 표현식을 unwrapping하면 non-optional type으로 결과가 리턴된다.





Optional Binding (옵셔널 바인딩)

optional binding은 옵셔널에 값이 있는지 확인할 때 사용한다. 만약 옵셔널에 값이 있다면 옵셔널에서 추출한 값을 일정 블록 안에서 사용 할 수 있는 상수나 변수로 할당해서 non-optional 상태로 사용할 수 있다. if, while, guard와 결합하여 사용한다.

Optional Binding 선언

if let name: Type = OptionalExpression {
    statements
}

while let name: Type = OptionalExpression {
    statements
}

guard let name: Type = OptionalExpression else {
    statements
}

Optional Binding 예시

if문

var num : Int? = nil

// if문
if num != nil {
    print(num!)
} else {
    print("nothing")
}

// if문 Optional Binding
num = 123
if var num = num {
    num = 456            // 456
    print(num)
}
print(num)    //    optional(123)

// 하나의 문장에서 여러 바인딩 사용
if let num = a, let str = b, str.count > 2 {
    print(num, str)
}

guard문

var num : Int? = nil

// guard문 방법1
if let n = num {
    print(n)
} else {
    print("nothing")
}

// guard문 방법2
if let num = num {        
    print(num)                
} else {
    print("nothing")
} 
// 옵셔널 바인딩에서는 임시 상수의 이름을 같은 이름을 사용해도 된다.
// num은 Local Scope에서만 사용된다.

// guard문 방법3
var str: String? = "str"
guard let str = str else {
    fatalError()
      str // error
// 옵셔널 바인딩한 상수는 else 블럭 다음에서 사용할 수 있다. else 블럭 사용불가.
}
print(str)    // str




Implicitly Unwrapped Optionals (IUO, 암시적 추출 옵셔널)

Implicitly Unwrapped Optionals(IUO)로 지정된 타입은 일반 값처럼 사용할 수 있으나, 여전히 옵셔널이기 때문에 nil도 할당할 수 있다. 추출할 때는 optional binding 이나 optional chaining 을 사용하는 편이 안전하다. 실제 코드에서는 자주 쓰이는 편은 아니다.

Implicitly Unwrapped Optionals(IUO) 선언

Type!

Implicitly Unwrapped Optionals(IUO) 예시

let num: Int! = 15
// 특정 조건에서 자동으로 추출된다.

let a = num
// a: Int?
// 형식으로 추론하는 경우 자동으로 추출되지 않는다.

let b: Int = num
// b: Int
// num 상수에 있는 값을 Int에 저장하려면 값을 unwrapping 해야하는데 IUO에서는 자동으로 unwrapping 된다.
// 특정 조건에서 자동으로 추출된다.
// 자동으로 추출해주기 때문에 강제 추출, 옵셔널 바인딩을 사용할 필요가 없다.
let num: Int! = nil
// IUO는 실제로 값이 있는지 확인하지 않기 때문에 nil을 부여하면 error 발생
let a = num
let b: Int = num    // error




Nil-Coalescing Operator (Nil 병합 연산자 ??)

Nil-Coalescing Operator 선언

a ?? b
OLptionalExpression ?? Expression

Nil-Coalescing Operator 예시

var msg = ""
var input : String? = "World"


// Optional Binding - 6줄의 코드
if let inputName = input {
    msg = "Hello, " + inputName
} else {
    msg = "Hello, Stranger"
}
print(msg)    // Hello, World


// 삼항 연산자 - 2줄의 코드
var str = "Hello, " + (input != nil ? input! : "Stranger")
print(str)    // Hello, World
// Nil-Coalescing Operator 이항 연산자
/*
 A. 값이 있을 경우
    1. input(옵셔널 표현식)이 값을 리턴하는지 확인한다.
    2. 값을 리턴한다면 이 값을 언래핑 한다음에 연산의 결과로 리턴한다.
 B. 값이 없을 경우
    1. input(옵셔널 표현식)이 값을 리턴하는지 확인한다.
    2. 값이 없다면 오른쪽 피연산자(Stranger)를 추출한다.
 */

var input : String? = "World"

// A. 값이 있을 경우
var str = "Hello, " + (input ?? "Stranger")
print(str)    // Hello, World

// B. 값이 없을 경우
input = nil
var str = "Hello, " + (input ?? "Stranger")
print(str)    // Hello, Stranger
댓글