티스토리 뷰
swift의 특징 중 하나인 optional에 대해 알아보자. 생소한 문법이라 처음에는 많이 놀랐는데, 알고 보면 익숙한 기능을 간결하게 작성할 수 있도록 해주는 문법이라는 것을 알 수 있다.
?
??????????
optional 변수를 선언하는 문법이다. 즉 변수에 적용시킬 수 있는 특징이라고 볼 수 있다. let으로 선언한 변수는 값이 바뀌지 않는 상수가 되고, var로 선언한 변수는 값이 변할 수 있는 변수가 되는 것과 마찬가지로 optional로 선언한 변수는 값을 가질 수도, 가지지 않을 수도 있다. 즉, optional로 선언된 변수는 값이 없는 nil을 담을 수 있다.
nil 값이 없는 “상태”를 말한다. Int 변수에 number에 0을 담는다고 해서 이 변수에 값이 없는 것은 아니다. 0이라는 값을 가지고 있는 것이다. nil은 0도 \n도 아닌 아무것도 없다는 상태를 나타낸다. |
반대로 ! 연산자를 사용해서 값을 가지고 올 수도 있다. 단, nil인 변수에 사용할 경우 실제로 nil을 가져오기 때문에 사용할 때 주의해야 한다.
다음 코드를 보자. normalString은 일반 변수이기 때문에 nil을 대입할 경우 컴파일 에러가 발생한다. 일반 변수는 반드시 값을 가지고 있어야 한다. String의 경우 초기화를 하지 않을 경우 “” 값을 가지고 있다.
var normalString: String = nil // error
var optionalString: String? = nil // fine :)
print(optionalString) // nil
활용
그렇다면 언제 optional을 사용할까? 기능 그대로 값이 있을 수도 없을 수도 있는 변수를 다룰 때 사용하면 된다.
먼저 optional을 사용하지 않는 예를 보자. 아래 예제 코드는 컴파일 에러가 발생한다. 초기화 되지 않은 name 변수를 출력하려고 했기 때문인데 name은 상황에 따라 초기화가 될 수도, 안될 수도 있는 변수 이기 때문에 문제가 생겼다. 사실 50% 확률로 name에는 "james"라는 값이 들어가게 되는데 이걸 컴파일 단계에서 잡아낼 수 있다는 점이 신기하다.
var name: String
// arc4random_uniform(max) : generate random number under the 'max' value
if arc4random_uniform(100) < 50 {
name = "james"
}
print("hello, my name is \(name)") // error!
이제 이 변수를 optional로 만들면 컴파일이 된다.
var name: String?
// arc4random_uniform(max) : generate random number under the 'max' value
if arc4random_uniform(100) < 50 {
name = "james"
}
print("hello, my name is \(name)") // error!
c++의 포인터와 개념이 완전히 같지는 않지만 동작하는 모습이 비슷하기 때문에 비교하면서 이해하면 좀 더 이해가 쉽다.
아래 두 코드를 보자.
// swift
var number: Int? = 10
print(number)
// optional(10) : wrapped value
// how can approach pure 10 value?
// c++
int temp = 10;
int* number = temp;
cout << number << endl;
// temp's address &temp
cout << *number << endl;
// 10
optional인 number는 Int값을 가질 수도 nil을 가질 수도 있지만 Int로 초기화 했을 때 optional로 wrapping되어있는 것을 볼 수 있다. c++도 마찬가지로 10이라는 int변수를 가리키게 했지만 실제 10에 접근하기 위해서는 한 단계 포인터를 벗겨내는 연산을 해야 한다.
Optional Binding
이렇게 optional 변수에서 값을 꺼낼 수 있는 연산을 Optional Binding이라고 한다. 위에서 말했듯이 실제 c++의 *연산자 처럼 강제로 값을 가지고 오는 !연산자가 있다. 하지만 안에 들어있는 값이 nil일 경우 런타임 에러가 발생할 수 있기 때문에 swift는 좀 더 부드러운 방법을 제공한다.
var number: Int? = nil
print(number!) // unwrap optional
// nil
아래 예제를 보자. swift의 if문은 optional 변수를 검사해서 nil이 아니면 if문 내용을 실행한다. 따라서 50%확률로 James를, 50%확률로 영어를 못하는 사람을 만날 수 있다.
var name: String?
if arc4random_uniform(100) < 50 {
name = "James"
}
// optional binding
if (let realName = name) {
print("hello, my name is \(realName)")
}
else{
print("Sorry, I can't speak English well...")
}
Optional Chaning
먼저 optional변수에 들어있는 값이 nil인지 검사를 하고 nil이 아니라면 그 다음 작성된 함수 등을 실행하는 문법이다. ? 연산자를 사용하기 때문에 코드도 직관적이다. 아래 예제에서 볼 수 있듯이 name이 있으면 append를 한다는 의도가 코드에 드러난다.
var name: String?
if arc4random_uniform(100) < 50 {
name = "James"
}
name?.append(".T.Kirk") // don't execute append(after ?) if name is nil.
if (let fullName = name) {
prinf("Hello, I'm captain \(fullName)")
}
else{
print("Sorry, I can't speak English well...")
}
nil-coalescing
단어도 어려운 이 문법은 어떻게든 표현식을 줄이려고 노력하는 swift의 철학이 담겨있는 집약체와도 같다. 3항 연산자처럼 코드를 짧게 만들어준다.
var name: String?
if arc4random_uniform(100) < 50 {
name = "James"
}
let realName = name ?? "default"
// if name is nil, realName set to 'default'
// else set to name
optional 변수가 현재 가지고 있는 값이 nil인지 먼저 검사하고 nil이 아니라면 들어있는 값을, nil이라면 default 값을 대입하게 된다. swift 표현법이 좀 더 짧긴 하지만 아직까지 c style에 익숙해서 그런지 c style이 더 직관적인것 같다. 익숙해져야겠다.
'Programming > Swift' 카테고리의 다른 글
Swift Beginner | 함수(1) (0) | 2020.11.18 |
---|---|
Swift Beginner | 반복문 (0) | 2020.11.18 |
Swift Beginner | 조건문 (0) | 2020.11.18 |
Swift Beginner | 변수 (0) | 2020.11.18 |
Swift - 인터페이스 (0) | 2018.03.29 |
- Total
- Today
- Yesterday
- JSP
- 드라마
- SHADER
- DesignPattern
- scala
- 자료구조
- swift
- ios
- mongoDB
- 데이터베이스
- rxswift
- machine learing
- Git
- SwiftUI
- OS
- 알고리즘
- 운영체제
- Spring
- 국내여행
- game
- C/C++
- 수학
- winsock
- C++
- Java
- database
- Cocos2d-x
- C
- SOCKET
- ue4
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |