Dev/Swift

Swift: 옵셔널(Optional)

두넌 2023. 5. 14.

DAY 05

옵셔널(optional)

 

Int형 vs Optional Int형


 

Int

  • Int형 값을 저장
  • var x : Int = 10

값 10이 변수 x에 저장됨

Int?, Int!

  • Int형 값을 저장 or 값이 없음(nil)
  • var y : Int? = 10
  • var z : Int!

값 Optional(10)이 변수 y에 저장됨

 

옵셔널 타입(Optional Type)


값을 반환할 때 오류가 발생할 가능성이 있는 값은 옵셔널 타입이라는 객체로 감싸서 반환함

Int("Hi") 와 같은 경우 정수 값을 반환할 수 없으므로 nil을 반환해야 하는데,
Swift 기본 자료형에서는 nil값을 저장할 수 없으므로 Optional Type으로 선언해야 함

 

  • 옵셔널 타입은 변수 또는 상수에 아무런 값이 할당되지 않는 상황을 안전하게 처리하기 위한 방법 제공
  • 옵셔널 타입 변수를 선언하기 위해서는 타입 선언부 뒤에 ? 문자를 씀

 

옵셔널 타입 강제 언래핑(forced unwrapping)


옵셔널 변수에 값이 있으면 옵셔널로 래핑되었다(wrapped)라고 함

옵셔널에 래핑된 값은 강제 언래핑(forced unwrapping)으로 풀어줌

var x: Int?
var y: Int = 0
x = 10
print(x)
print(x!)
print(y)

output

Optional(10)
10
0

print(x)에서 x는 : Int? 옵셔널 변수로 선언되었기 때문에 출력결과 Optional(10)으로 출력된다

print(x!)에서는 x가 x! 키워드로 강제 언래핑되어 출력되었기 때문에 Int형 10이 출력됨

 

만약 x = x+2 와 같은 연산을 시도한다면, 옵셔널 타입과 Int타입이 계산되지 않기 때문에 오류가 발생함
var x: Int?
x = 10
if x != nil {
    print(x!)
} else {
    print("nil")
}

출력결과 x가 강제 언래핑되어 x!인 10이 출력된다

 

강제 언래핑(forced unwrapping) - optional binding


 

강제 언래핑하는 또 다른 방법으로, 옵셔널 바인딩(optional binding)을 이용하여 옵셔널에 할당된 값을 임시 변수 또는 상수에 할당

if let constantName = optionalName {
    // if not nil - run this
}

if var variableName = optionalName {
    // if not nil - run this
}

다음과 같은 형식으로 표현하는 것이 일반적이며, optionalName에 담긴 값을 임의의 상수 혹은 변수로 optional binding을 통해 값을 언래핑시킬 수 있음

var x: Int?
x = 10
if let xx = x {
    print(xx)
} else {
    print("nil")
}
var x1: Int?
if let xx = x1 {
    print(xx)
} else {
    print("nil")
}

output

10
nil

optional Int인 x의 값을 상수 xx로 optional binding시켜 Int로 unwrapping하고 값을 출력

x1은 nil이기 때문에, "nil"을 출력함

 

여러 옵셔널 변수를 한번에 언래핑하는 방법


 

var pet1: String?
var pet2: String?
pet1 = "cat"
pet2 = "dog"
if let firstPet = pet1, let secondPet = pet2 {
    print(firstPet, secondPet)
} else {
    print("nil")
}

다음과 같이 if문의 comma(,)를 이용하여 여러 옵셔널 변수를 한번에 언래핑할 수 있다

 

두 가지 옵셔널 타입


옵셔널이 항상 유효한 값을 가질 경우 옵셔널이 암묵적인 언래핑(implicitly unwrapped)이 되도록 선언할 수 있다

이러한 방법으로 옵셔널이 선언된다면 강제 언래핑이나 옵셔널 바인딩을 하지 않아도 값에 접근할 수 있음

암묵적인 언래핑으로 옵셔널을 선언하기 위해서는 선언부에 물음표(?) 대신 느낌표(!)를 사용

var x: Int?

var y: Int!

 

스위프트 공식 문서 참조
Implicitly Unwrapped Optional

일반 옵셔널 값으로 사용하려고 하지만, optional로 사용할 수 없는 경우 swift는 값을 강제로 푼다

Optional로 사용되지 않으면 강제로 unwrap한다

let a: Int! = 1
let b: Int = a
let c: Int = a!
let d = a
let e = a + 1

print(a, b, c, d, e)
print(type(of:a), type(of:b), type(of:c), type(of:d), type(of:e))

output

Optional(1) 1 1 Optional(1) 2
Optional<Int> Int Int Optional<Int> Int

a는 implicitly unwrapped으로 옵셔널이 선언되어 타입은 Optional<Int>이지만, b에서 Optional로 사용될 수 없으므로 강제로 unrwapping 하는것을 볼 수 있다

c처럼 굳이 a를 강제 언래핑 하지 않아도 사용할 수 없는 경우 강제로 unwrapping 해준다

하지만 d처럼 type을 명시하지 않은 경우는 그대로 Optional 타입으로 선언된다

 

Any와 AnyObject


AnyObject(protocol)

어떠한 클래스의 객체도 저장할 수 있음

클래스만 허용하며 구조체나 열거형은 허용하지 않음

Any

어떠한 타입도 표현할 수 있다

클래스, 구조체, 열거형, 함수타입도 가능

var x: Any = "Hi"
print(x, type(of:x))
x = 10
print(x, type(of:x))
x = 3.5
print(x, type(of:x))

output

String
Int
Double

다음과 같이 값이 초기화될 때 마다 타입이 변한다

댓글