공부 연습장 :-)

옵셔널의 정리 - 옵셔널의 개념, 옵셔널 바인딩, 암묵적 언래핑

|

옵셔널 Optional

스위프트의 옵셔널은 일종의 안전장치이다. 예상치 못한 곳에서 nil이 발생하여 프로그램이 예기치 않게 종료되는 것을 막기위해 사용한다. nil이 될 수 있는 인스턴스는 반드시 옵셔널타입으로 선언해야한다.

반대로, 옵셔널타입으로 선언되어있지 않은 인스턴스는 nil이 되지 못한다! (일반 자료형에 nil은 억지로 대입할 수도 없음)

옵셔널 바인딩

if let에서 언래핑과정이 암묵적으로 수행되어 옵셔널의 값이 임시 상수로 지정된다.(theError)

var errorCodeString: String?
errorCodeString = "404"

if let theError = errorCodeString {
    print(theError)
}
//errorCodeString이 nil이 아니면 theError에 값을 대입하고 출력해라.

/*
옵셔널 바인딩
if let tempConstant = anOptional {
    //tempConstant가 nil이 아니면 어떤 일을 한다.
} else {
    //anOptional에는 값이 없다.(nil이다.)
}
*/
옵셔널 바인딩 중첩
var errorCodeString: String?
errorCodeString = "404"

if let theError = errorCodeString {
    if let errorCodeInteger = Int(theError) {
        print("\(theError): \(errorCodeInteger)")
    }
}

여러 옵셔널 언래핑 & 추가판단

옵셔널바인딩을 중첩하지않고 여러 옵셔널 값을 바인딩 하는 방법도 있다.

if let theError = errorCodeString, let errorCodeInteger = Int(theError) {
        print("\(theError): \(errorCodeInteger)")
    }

먼저 errorCodeString을 언래핑하여 그 값을 theError에 저장하고, Int인스턴스로 변환했다. 그 결과는 옵셔널이기때문에(?) 언래핑하여 그 값을 errorCodeInteger로 바인딩했다.

  • 이렇게 여러 옵셔널을 바인딩 하는 구문에서는 두 바인딩에서 한 번이라도 nil이 리턴되면 조건문의 실행 코드는 동작하지 않는다.
  • 추가 판단은 errorCodeInteger == 404부분인데, 이는 앞의 두 옵셔널이 언래핑되어서 nil이 리턴되지 않는 조건, 이후에 추가로 errorCodeInteger가 404인 조건을 뜻한다. 이렇게 if문의 모든 조건이 만족할 시에 그 다음 코드가 실행된다. 옵셔널 바인딩과 추가 판단조건을 같이 ,와 함께 써주어도 문법에 맞는다는게 특징인 것 같다.

옵셔널 체이닝

var errorCodeString: String?
errorCodeString = "404"
var errorDescription: String?

if let theError = errorCodeString, let errorCodeInteger = Int(theError), errorCodeInteger == 404 {
    errorDescription = "\(errorCodeInteger + 200): resource was not found."
} //errorDescription의 타입은 String? 이다.

var upCaseErrorDescription = errorDescription?.uppercased()
//"604: RESOURCE WAS NOT FOUND."
errorDescription
//"604: resource was not found."

<코드설명> errorCodeString은 String?타입이다. theError에 errorCodeString이 nil이 아니면 값을 대입힌다. theError의 타입은 String이다. 이를 Int로 변환해서 errorCodeInteger에 대입한다. (errorCodeInteger의 타입은 Int이다.) 만약 그 errorCodeInteger의 값이 404이면 그 다음의 코드가 실행된다.

upCaseErrorDescription는 에러메시지(errorDescription , String?타입)을 모두 대문자로 표현하는 인스턴스이다. errorDescription에 붙은 ?는 옵셔널 체이닝이다.

errorDescription에 값이 없을때는 대문자로 변환할 문자가 없으므로 upCaseErrorDescription이 nil로 설정된다. 이 시점에서 옵셔널 체이닝에 따라 옵셔널이 리턴된다. 하지만 errorDescription에 값이 있기 때문에 설명 텍스트를 대문자로 반환했고, 변환된 결과를 upCaseErrorDescription에 지정했다. 따라서 결과는 대문자로 반환된 메시지가 출력된다.

nil 결합 연산자

옵셔널에서 값을 가져오거나 옵셔널 값이 nil이면 어떤 동작을 해라 라는 단순한 연산 (ex. print(“Error”)같은 단순한 동작이 else문 뒤에 오는 것)일때 ??를 사용하면 간단히 작성 할 수 있다.

let description: String
if let errorDescription = errorDescription {
  description = errorDescription
} else {
  description = "No Error"
}
// 단순한 연산인데도 코드가 너무 길다.

이 코드는 아래의 코드와 동일하게 작동한다!

let description = errorDescription ?? "No Error"

??의 왼쪽에는 옵셔널이 와야하고, 오른쪽은 비옵셔널타입이 와야한다. errorDescription은 옵셔널타입. 왼쪽 옵셔널이 nil이면 ??는 오른쪽 값을 리턴한다. 왼쪽 옵셔널이 nil이 아니면 옵셔널에 포함된 값이 리턴된다!

errorDescription = nil
let description = errorDescription ?? "No Error"
//결과 사이드바에는 "No Error"가 표시된다.

Comments