Swift) 옵셔널(Optional)

Havi·2020년 12월 8일
0

Swift기초

목록 보기
6/19
post-custom-banner

옵셔널이란

옵셔널(Optional)이란 nil을 사용할 수 있는 타입으로, 옵셔널 타입(Optional Type)이라 부른다.

옵셔널은 Type casting이나 nil value 체크 등에 있어 Swift의 안전한 코딩을 도와주는 언어입니다.

옵셔널을 해제하는 방법은 명시적 해제묵시적 해제가 있고, 명시적 해제 에는 강제해제비강제 해제, 묵시적 해제컴파일러에 의한 자동해제, !연산자를 이용한 자동 해제로 나눌 수 있다.

옵셔널 강제 해제

!를 붙이면 강제해제된다. 단 강제해제는 위험하므로 nil이 아닐 때를 점검하는 것이 좋다.

var str = "123"
var intFromString = Int(str) // Optional Int형

if intFromString != nil {
	print("값은 \(intFromString) 입니다.")
} else {
	print("변환 실패")
}

옵셔널 바인딩

옵셔널 바인딩(Optional Binding)이란 if구문 내에서 조건식 대신 옵셔널 값을 일반 상수나 변수에 할당하는 구문을 사용하는 방식이다.

옵셔널 바인딩은 조건문 내에서 일반 상수에 옵셔널 값을 대입하는 방식으로 이루어진다.

//if문을 이용한 Optional Binding
var str = "123"

if let intFromStr = Int(str) {
	print("값은 \(intFromString) 입니다.")
} else {
	print("변환 실패")
}
//guard문을 이용한 Optional Binding
var str = "123"

guard let intFromStr = Int(str) else {
	print("변환 실패")
    	return
} 
	
print("값은 \(intFromString) 입니다.")

guard문의 경우 진행이 불가능할 정도로 큼 일이 생길때만 사용

컴파일러에 의한 자동해제

옵셔널 강제해제나 옵셔널 바인딩을 하지 않아도 컴파일러가 자동으로 해제해주는 경우가 있다.

비교연산의 경우 옵셔널을 해제하지 않아도 자동으로 연산을 수행

let tempInt = Int("1234")

tempInt == 123 // true
tempInt == Optional(123) // true
tempInt! == 123 // true
tempInt! == Optional(123) // true

묵시적 해제 (Implicitly Unwrapped Optional)

값을 사용할 때 자동으로 옵셔널이 해제되기 때문에 굳이 ! 연산자를 사용하지 않아도 된다.

변수의 값이 nil이 될 가능성이 있다면 묵시적 옵셔널 해제를 사용하면 안된다.

let str: String? = "Optional"
var str2: String! = "Not Optional"

print(str) //Optional("Optional")
print(str2) //Not Optional

str2 = nil // 문제 없음

var val: Int? = 5
val + 5 // 오류 - Optional Int + Int

var val2: Int! = 5
val2 + 5 // 10

// 형식상 옵셔널로 정의하지만 실제로 사용할 때에는 절대 nil이 될 가능성이 없는 변수일 때 묵시적 해제 사용
var value: Int! = Int("123")

옵셔널 타입의 문제점

옵셔널을 해제하려면 if구문을 통해 정상값 여부를 검사해야한다.

하지만 다음 코드와 같은 경우 코드가 상당히 복잡해진다.

struct Company {
var ceo: Human?
var companyName: String?
}

struct Human {
var name: String?
var man: Bool = true
}

var startUp: Company? = Company(ceo: Human(name: "나대표", man: false), companyName: "루비페이퍼")

// 옵셔널 해제가 까다로움
if let company = startUp {
	if let ceo = company.ceo {
    		if let name = ceo.name {
        		print("대표 이름 : \(name)")	
        	}
        }
}

// 간단하게 하기 위해 !강제해제를 사용할 경우 런타임 에러 확률이 높다
if let name = startup!.ceo!.name {
	print(name)
}

이런 경우 옵셔널 체인을 사용한다.

옵셔널 체인

안정성 검사를 하지 않고 메소드나 프로퍼티를 호출하더라도 오류가 발생하지 않는 문법을 옵셔널 스타일을 이용하여 구현

startUp?.ceo는 startUp이 nil이 아닐 때 동작하고 nil이면 아무 동작도 하지 않는다.

따라서 위의 코드는 다음과 같이 사용할 수 있다.

if let name = startUp?.ceo?.name { //마지막 name은 옵셔널 체인에 해당하지 않음
	print("대표 이름 : \(name)")
}

옵셔널 체인에는 다음과 같은 특징이 있다.

  1. 옵셔널 체인으로 참조된 값은 무조건 옵셔널 타입으로 반환된다.
  2. 옵셔널 체인 과정에서 옵셔널 타입들이 겹쳐있더라도 한번만 처리된다.
//ex)
let name = startUp?.ceo?.name

print(name) // Optional("나대표")

//Optional(Optional(Optional(123))) == Optional(123)

따라서
옵셔널 체인 구문 : startup!.ceo!.name과
옵셔널 강제 해제 구문 : startup?.ceo?.name은
비슷하지만, 옵셔널 체인에서는 nil 오류가 발생하지 않는다는 차이가 있다.

헷갈릴 수 있는 예제 정리

출처

profile
iOS Developer
post-custom-banner

0개의 댓글