본문 바로가기

Swift

Swift - Optional(옵셔널)

Swift Optional(옵셔널)

 

- Optional은 Swift 언어에서 프로그램의 안정성을 높이기 위해 도입한 개념.

- 기존 프로그래밍 언어를 가지고 작업을 할때 가장 빈번히 발생하는 예외 중의 하나가 NULLPointerException임. 

- NULLPointerException은 주로 변수(상수)메모리의 값을 할당 하지 않은 상태에서 해당 변수나 상수에 접근시 발생.

- Swift에서는 이러한 Nullpointerexception을 방지하기 위해서 Optional형식을 도입.

- Optioanl 형식은 nil을 저장할 수 있도록 자료형 * nil: 값이 없다는 뜻.

- optional 자료형을 만들고자 하는 경우에는 변수를 선언할 때 자료형 뒤에 ?나!를 붙여서 만듬.

- optional 자료형으로 만들어지면 nil을 저장할 수 있음. 

- Optional 은 형식의 데이터를  wrapping을 해서 가지고 있음. 

- 그래서, optional 자료형의 값은 일반 연산작업이 안되고 다른 자료형과 연산도 안됨.  프린트 함수를 사용하여 로그 출력을 해보면 되면 optional이 붙어서 출력됨.

 

중요:

 -스위프트는 일반 자료형으로 변수를 선언하면 nil을 저장할 수 없음. (무조건 값을 할당하여 초기화를 해야 함.)

- 즉, 변수나 상수는 접근하기 전 반드시 “초기화"를 해줘야 함.  

 

이해를 돕기 위해 아래 코드를 참고해 보자.

 

var su1 : Int // error

// swift에서는 위와 같이 변수선언을 할 수 없음. 스위프트에서는 optional타입이 아니면 nil을 저장할 수 없기때문.

// 아래처럼 ? 나 ! 를 형식뒤에 붙여 Optional 형식으로 사용해야 nil값을 저장할 수 있음. 

var su2 : Int? = nil   // OK

su2 = 30    // OK 

var su1 : Int = 10  // OK 

// 아래와 같이 optional타입은 연산에 사용할 수 없음. 

var result : Int = su1 + su2  // su2가 옵셔널INT 형식이라 연산에 사용할 수 없어서 에러. 

 

// optional type은 출력을 하게되면 optional이 붙어서 출력.

print("su1:", su1)

print("su2:", su2)

 

정리: optional 자료형의 값은 일반 연산작업이 안되고 다른 자료형과 연산도 안됨.  그래서 로그출력을 하게 되면 optional이 붙어서 출력됨.

 

중요 사항:

  1. 옵셔널 값을 사용하려면 반드시 unwrapping을 해야만 함. 

  2. 아래 정리한 Optional Unwrapping 방법 중, 주의할 사항은 nil이 들어있는 변수(상수)를 강제 unwrapping하게 되면 critical error가 발생한다. 

  3. 그래서, optional binding을 통해 값을 추출하는 것을 권장함.

옵셔널 Unwrapping

 

var num: Int? = nil 

num = 123 

print(num)  → Optional(123)으로 출력됨. 

-이해를 돕기위해 값이 상자 안에 포장되어 있다고 생각하면 좋음. 이 상자를 여는 것을 unwrapping이라고 함. 

 

 

Optional해제 (unwrapping)

  1. 강제로 해제(Forced Unwrapping) : (비권장)

=> optional타입의 자료형을 선언할때 뒤에 !를 붙이면 강제로 해제 

=> 데이터가 nil을 가지고 있으면 예외가 발생함. 

=> 이 방법을 사용할 때는 if나 guard구문을 이용해서 nil이 아닐때만 수행하도록 하는 것이 좋음. 

 

//optional을 강제로 해제해서 사용

print("su2", su2!)

var result : Int = su1 + su2!

print("result", result)

//강제 해제를 사용할 때 데이터가 nil이면 에러 발생

su2 = nil

print("su2:", su2!)  //Fatal error: Unexpectedly found nil while unwrapping an Optional value

result = su1 + su2!

아래와 같은 방법으로 unwrapping.

if su2 != nil {

    print("su2:", su2!)

    result = su1 + su2!

} else {

    print("su2가 nil이라서 작업을 계속할 수 없습니다.")

}

 

 2.  컴파일러에 의한 자동해제 

⇒ == 와 != 연산에 사용할 때는 컴파일러가 자동으로 해제해서 사용. 

 

 3. 묵시적 해제 

=> 변수를 만들때 ? 대신에 !를 붙이면 변수 사용을 할 때 Optional을 해제하지 않아도 자동으로 해체가 됨. 

=> nil 인 경우는 예외가 발생할 수 있음. 

=> iOS에서는 Interface Builder에서 디자인 한 UI객체를 swift코드에 변수로 만들 때 이방법을 사용함.

var su3 : Int? = 34

// == 와 != 연산은 optional을 해제하지 않아도 가능.

print(su3 == 34)

// ? 대신에 !를 이용해서 변수를 만들면 optional을 해제하지 않아도 자동으로 해제해서 사용할 수 있도록 해줌. 

var su4 : Int! = 76

print(su4 + 70)

 

4. 옵셔널 바인딩 (권장) 

if let name:Type = optionalexpression { 

  statements

여기서 타입은 형식추론이 가능하기 때문에 생략가능.

if var도 가능. 

 

OptionalExpression에서 값이 있는지 확인 후, 값이 있다면 name상수에 언랩핑 되어서 추출함.

 

Optional 표현식을 평가한 값을 언랩핑하여 상수에 저장함. 

var num: Int? = nil

print(num!)

// 아래처럼 작성하는 경우는 거의 없음. 

if num != nil { 

   print(num!)

}

 

정석 문법:

 

if let name:Type = optional expression { 

  statements

while let name: Type = optional expression { 

 statements

}

—————————————————————-

if let 바인딩할상수이름 = optional표현식 {

   statements  // 여기서만 바인딩된 상수를 쓸 수 있음.

}

 

if let 상수 이름 = 반드시옵셔널표현식이 와야 함. { 

     statements

}

 

중요: 바인딩된 상수는 if블럭 안에서만 사용할 수 있음. 

 

중복 중첩되는 경우에는 guard let 사용. 주의:  가드문의 else block은 가드문자체가 아니라 가드문을 호출한 호출문을 종료시키는 것임.

 

guard let name:Type = optional expression else { 

statements

 

'Swift' 카테고리의 다른 글

Swift - Self & Super  (0) 2020.03.22
Swift - 고차 함수  (0) 2020.03.21
Swift - First Class Citizen  (0) 2020.03.19
Swift - Closure(클로저)  (0) 2020.03.19
Swift - Function(함수)  (2) 2020.03.19