๐ก ์ค์ํํธ์ ํน๋ณํ ๊ธฐ๋ฅ ๊ฐ์ด๋ฐ ํ๋์ธ ์ต์ ๋(Optional)์ ๋ํด ์์๋ณด์!
[Contents]
- ์ต์ ๋ ์ด๋?
- ์ต์
๋ ์ถ์ถ
- ๊ฐ์ ์ถ์ถ(Forced unwrapping)
- ์ต์
๋ ๋ฐ์ธ๋ฉ(Optional Binding)
- 2.1. ์ต์ ๋ ๋ฐ์ธ๋ฉ ์ค์ฒฉ
- 2.2. nil ๊ฒฐํฉ ์ฐ์ฐ์
- ์์์ ์ถ์ถ ์ต์ ๋(Implicitly Unwrapped Optional)
- ์ต์ ๋ ์ฒด์ด๋(Optional Chaining)
- String ๋น๊ฐ, ์ต์ ๋ ๊ตฌ๋ถ
๐ ์ต์ ๋(Optional) ์ด๋?
- ์ผ์ข ์ ์์ ์ฅ์น๋ก ๋ณ์ ์์ ๊ฐ์ด ์์ ์๋, ์์ ์๋(nil) ์๋ค๋ ๊ฒ์ ์ต์ ๋ ๋ณ์ ์ ์ธ ? ํค์๋ ์ฌ์ฉํ์ฌ ํํํ๋ค.
- ์ฆ, nil์ด ๋ ์๋ ์๋ ์ธ์คํด์ค๋ ๋ฐ๋์ ์ต์ ๋ ํ์ ์ผ๋ก ์ ์ธํด์ผ ํ๋ค.
- ์ฆ, ์ต์
๋๋ก ์ ์ธ๋ ๋ณ์์๋ง! nil ํ ๋น ๊ฐ๋ฅ!
- ์ต์ ๋์ด ์ ์ฉ๋ ์ด๋ค ํ์ ์ ์ธ์คํด์ค์๋ nil์ด ๋ ์ ์๋ค.
- ๋ฐ๋ฉด์, Objc๋ ๊ฐ์ฒด๋ง nil ์ง์ ๊ฐ๋ฅ
var city: String? = "Seoul"
print(city) //Seoul
city = nil
print(city) //nil
- ์ต์ ๋์ด ์๋ ๋ณ์์๋ ์ต์ ๋ ๊ฐ์ด ๋ค์ด๊ฐ ์ ์๊ณ ์ฐ์ฐ๋ ๋ถ๊ฐ!! ์ถ์ถํด์ ํ ๋นํด์ฃผ์ด์ผ ํจ
var number1:Int? = 20
var number2:Int = 100
number1 = number2 //๊ฐ๋ฅ
//number2 = number1 //๋ถ๊ฐ๋ฅ
//let sum = number1 + number2 //๋ถ๊ฐ๋ฅ
๐ ์ต์ ๋(Optional) ์ถ์ถํ๊ธฐ - ์ต์ ๋ ํด์ (Optional Unwrapping)
โ๏ธ 1. ๊ฐ์ ์ถ์ถ(Forced unwrapping)
- ์ต์ ๋์ ๊ฐ์ ๊ฐ์ ์ถ์ถํ๋ ค๋ฉด ์ต์ ๋ ๊ฐ์ ๋ค์ ๋๋ํ(!)๋ฅผ ๋ถ์ฌ์ฃผ๋ฉด ๊ฐ์ ๋ก ๊ฐ์ ์ถ์ถํ์ฌ ๋ฐํ ๊ฐ๋ฅํ๋ค.
- ํ์ง๋ง, ๊ฐ์ ์ถ์ถ์ ์ต์ ๋์ ๊ฐ์ด ์๋ ๊ฒฝ์ฐ(nil์ด ์๋ ๊ฒฝ์ฐ), ๋ฐํ์ ์ค๋ฅ๊ฐ ๋ฐ์
var food: String? = "pizza"
print(food) //Optional("pizza")
print(food!) //pizza
food = nil
//print(food!) //๋ฐํ์ ์ค๋ฅ ๋ฐ์!!!
โ๏ธ 2. ์ต์ ๋ ๋ฐ์ธ๋ฉ(Optional Binding)
- ์ต์ ๋์ ๊ฐ์ด ์๋์ง ํ๋จํ ์ ์๋ ์ ์ฉํ ํจํด์ด๋ค.
- ์ต์ ๋ ํ์ ์ ๊ฐ์ ์์ ํ๊ฒ ์ถ์ถํ๊ธฐ ์ํด ์ฌ์ฉ
- ์ต์ ๋์ ๊ฐ์ด ์๋ค๋ฉด ์ต์ ๋์์ ์ถ์ถํ ๊ฐ์ ์์๋ ๋ณ์๋ก ํ ๋นํด์ ์ฌ์ฉํ ์ ์๋๋ก ํด์ค.
- ์ต์ ๋ ๋ฐ์ธ๋ฉ์ if ๋๋ while ๊ตฌ๋ฌธ ๋ฑ๊ณผ ๊ฒฐํฉํ์ฌ ์ฌ์ฉ ๊ฐ๋ฅ.
- ๋ฐฉ๋ฒ์๋ ํฌ๊ฒ if let ๊ตฌ๋ฌธ๊ณผ guard let ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์์
- if let
- guard let
- nil ์ฒดํฌ์ ํจ๊ป ์กฐ๊ฑด๋ฌธ ์์ฑ ๊ฐ๋ฅ
- ๋ฐ๋์ return ์ด๋ throw ์ฒ๋ผ ํด๋น ๋ฉ์๋๋ ํ๋์ด ์ข ๋ฃ๋๋ ๋ช ๋ น์ด ํฌํจ๋์ด์ผ ํ๋ค.
let tmpString : String? = "Hello"
//2-1. if let ์ฌ์ฉ
if let opt1 = tmpString {
// ๊ฐ์ด ์๋ ๊ฒฝ์ฐ
print(opt1)
}else{
// ๊ฐ์ด ์๋ ๊ฒฝ์ฐ
print("๊ฐ ์์")
}
//2-2. guard let ์ฌ์ฉ
func bindingWithGuard() {
guard let opt2 = tmpString else{
// ๊ฐ์ด ์๋ ๊ฒฝ์ฐ
return
}
// ๊ฐ์ด ์๋ ๊ฒฝ์ฐ
}
2.1. ์ต์ ๋ ๋ฐ์ธ๋ฉ ์ค์ฒฉ
์ต์ ๋ ๊ฐ์ด ๋ง์ ๊ฒฝ์ฐ, ์๋ ์ฝ๋์ ๊ฐ์ด ์ต์ ๋ ๋ฐ์ธ๋ฉ ์ค์ฒฉ๋๋ ๊ฒฝ์ฐ๋ค์ด ์๋๋ฐ,
์ด์ค ์ ๋๋ ๊ด์ฐฎ์ง๋ง ์ผ, ์ฌ์ค์ผ๋ก ์ค์ฒฉ๋๋ ๊ฒฝ์ฐ, ์ฝ๋๊ฐ ์ง์ ๋ถํด์ง๋ค.
var errorCodeString: String?
errorCodeString = "404"
if let theError = errorCodeString{
if let errorCodeInteger = Int(theError){
//Int(theError)๊ฐ ์ ์๊ฐ์ด ์๋ ๊ฒฝ์ฐ, ์ต์
๋ ๋ฆฌํดํ๋ฏ๋ก ์ต์
๋ ๋ฐ์ธ๋ฉ ํ์
printName("\(theError) : \(errorCodeInteger)")
}
}
๋ฐ๋ผ์, ์๋์ ๊ฐ์ด ์ต์ ๋ ๋ฐ์ธ๋ฉ์ ํ์ค๋ก๋ ํํ ๊ฐ๋ฅํ๊ณ , ์ถ๊ฐ์ ์ผ๋ก ์กฐ๊ฑด๋ฌธ ์ถ๊ฐ๋ ๊ฐ๋ฅํ๋ค.
var errorCodeString: String?
errorCodeString = "404"
if let theError = errorCodeString, let errorCodeInteger = Int(theError), errorCodeInteger == 404{
printName("\(theError) : \(errorCodeInteger)")
}
2.2. nil ๊ฒฐํฉ ์ฐ์ฐ์(nil coalescing operator)
์๋์ ๊ฐ์ด ์ต์ ๋ ๋ฐ์ธ๋ฉ์ผ๋ก ๊ธฐ๋ณธ๊ฐ์ ์ธํ ํ ๋, ๋จ์ํ ์ฐ์ฐ์์๋ ์ฝ๋๊ฐ ์๋นํ ๊ธธ๋ค.
var errorCodeString: String?
errorCodeString = "404"
let description : String
if let theError = errorCodeString{
description = theError
}else{
description = "No error"
}โ
์ด๋ฐ ๊ฒฝ์ฐ, nil ๊ฒฐํฉ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ๊ฒ ํํ ๊ฐ๋ฅํ๋ค.
let description = errorCodeString ?? "No error"
nil ๊ฒฐํฉ ์ฐ์ฐ์ ํํ๋ฒ์ ์ฝ๊ฒ ํํํ๋ฉด,
์๋ ์ฝ๋์์
a๋ณ์์ b์ ๊ฐ์ด ์์ผ๋ฉด(), b๋ฅผ ๋ฃ๊ณ ,
var b : String? = "test"
let a = b ?? "Nothing"
print(a)
//test ์ถ๋ ฅ
b์ ๊ฐ์ด ์์ผ๋ฉด(var b : String?), "Nothing"์ ๋ฃ์ ๊ฒ์ด๋ค.
var b : String?
let a = b ?? "Nothing"
print(a)
//Nothing ์ถ๋ ฅ
โ๏ธ 3. ์์์ ์ถ์ถ ์ต์ ๋(Implicitly Unwrapped Optional)
- ์์์ ์ถ์ถ ์ต์ ๋์ ์ฌ์ฉํ๋ ค๋ฉด ์ ์ธ์ ํ์ ๋ค์ ๋๋ํ(!)๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
- ์์์ ์ถ์ถ ์ต์ ๋๋ก ์ง์ ๋ ํ์ ์ ์ผ๋ฐ ๊ฐ์ฒ๋ผ ์ฌ์ฉํ ์ ์์ผ๋, ์ต์ ๋์ด๊ธฐ ๋๋ฌธ์ nil๋ ํ ๋นํ ์ ์๋ค.
//!์ฌ์ฉํ์ฌ ์ ์ธ
var myPhone: String! = "iPhone"
print(myPhone) //iPhone
//nil ํ ๋น ๊ฐ๋ฅ
myPhone = nil
- nil์ด ํ ๋น๋์ด ์์ ๋ ์ ๊ทผ์ ์๋ํ๋ฉด ๋ฐํ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
- ์ฆ, ํน๋ณํ ๊ฒฝ์ฐ๋ก๋ง ์ ํํ์ฌ ์ฌ์ฉํ๋ ๊ฒ์ด ์ต์ ์ด๋ค!!!!
- ๊ทธ๋ ๋ค๋ฉด, ์๋ ์ฝ๋๊ฐ ์ ์๋ํ ๊น?
var errorCodeString2: String! = nil
let anotherErroCodeString: String = errorCodeString2
let yetAnotherErroCodeString = errorCodeString2
์ ๋ต์
- ๋๋ฒ์งธ ๋ผ์ธ์์๋ ์ต์ ๋๋ก ์ง์ ๋์ง ์์ ๋ณ์์ ๋ฃ์๊ธฐ ๋๋ฌธ์ ๋ฐํ์ ์ค๋ฅ๊ฐ ๋ฐ์!
- ์ธ๋ฒ์งธ ๋ผ์ธ์์๋ nil์ด ํ ๋น๋๊ณ , yetAnotherErrorCodeString์ String? ์ธ์คํด์ค๊ฐ ๋์ด ์ฝ๋์ ์์ ์ฑ์ ๋ด๋ณด๋๋ค. ํ์ง๋ง, ์ปดํ์ผ๋ฌ๋ ๋ช ์์ฑ์ ์๊ตฌํ๋ค. ๋ฐ๋ผ์ ์๋์ ๊ฐ์ด ์๋ฌต์ ์ผ๋ก ์ธ๋ํ๋๋๋ก ์ ์ธ์ด ํ์ํ๋ค.
let yetAnotherErroCodeString: String! = errorCodeString2
โ๏ธ 4. ์ต์ ๋ ์ฒด์ด๋(Optional Chaining)
์ต์ ๋ ์ฒด์ด๋๋ ์ต์ ๋ ๋ฐ์ธ๋ฉ ์ฒ๋ผ ์ต์ ๋ ๊ฐ์ ์๋์ง ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ค.
์ฒด์ธ์์ ์ต์ ๋์ ๊ฐ์ด ์๋ค๋ฉด, ํธ์ถ์ ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํ๊ณ
๊ฐ์ด nil ์ด๋ผ๋ฉด, ์ฒด์ธ ์์ฒด๊ฐ nil์ ๋ฆฌํดํ๋ค.
์๋ ์ฝ๋์์ errorDescription์ ๋ถ์ ?๋ ์ต์ ๋ ๋ ์ด๋ ๊ณผ์ ์ ์์์์ ์๋ฆฐ๋ค.
var errorCodeString: String?
errorCodeString = "404"
if let theError = errorCodeString, let errorCodeInteger = Int(theError), errorCodeInteger == 404{
// printName("\(theError) : \(errorCodeInteger)")
errorDecription = "\(errorCodeInteger + 200) : resource was not found"
}
//์ต์
๋ ์ฒด์ด๋์ ์์!!
var upCaseErrorDecription = errorDecription?.uppercased()
//604 : RESOURCE WAS NOT FOUND ์ถ๋ ฅ
errorDecription
๋ฌธ์ )
์ต์ ๋์ด nil์ผ ๋, ๊ทธ ๊ฐ์ ์์ธ์คํ๋ฉด ๋ฐํ์์ค๋ฅ๊ฐ ์ผ์ด๋๋ค.
์ด ์ํฉ์ ๊ตฌํํ๊ณ , ๋ฐํ์ ์ค๋ฅ์ ๋ด์ฉ์ ํ์ ํ๋ผ. ๋จ, ๊ฐ์ ์ธ๋ํ์ ์ ์ฉํด์ผ ํ๋ค.
sol)
//๊ฐ์ ์ธ๋ํ์ ์ ์ฉํ ์ต์
๋์ด nil ์ธ ๊ฒฝ์ฐ
let optionalValue: String! = nil
//๊ฐ์ ์ก์ธ์คํ๋ฉด ๋ฐํ์ ์ค๋ฅ ๋ฐ์!
let runtimeValue: String = optionalValue
[์๋ฌ๋ด์ฉ]
error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
๐ฅ String ๋น๊ฐ, ์ต์ ๋ ๊ตฌ๋ถ
์ค์ํํธ์ String ์ต์ ๋์ ์ฝ๊ฐ ์ด์ํฉ๋๋ค.
String? ํ์ ์ “๋ถ๊ฐ๋ฅ”ํ ๊ฐ์ด ๋ ๊ฐ์ง ์์ต๋๋ค.
์๋, ์ต์ ๋ ํ์ ์ "๋น" String์ ๊ฒฝ์ฐ๊ฐ nil ์ธ ๊ฒฝ์ฐ์, "" ์ธ ๊ฒฝ์ฐ ์ด 2๊ฐ์ง ์ด๊ธฐ ๋๋ฌธ์ด์ฃ !!!!
์ด๊ฒ์ ๋ฒ๊ทธ์ ์์์น ๋ชป ํ ๋์์ ์ฒ๋ฆฌํ๊ณ ์ตํ๊ธฐ๊ฐ ๋ฒ๊ฑฐ๋กญ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
๋ฐ๋ผ์, ์ฒ๋ฆฌ๋ ์์ ๊ฐ์ด ์๋ nil์ ๊ฒฝ์ฐ์ผ ๋, ๊ฐ์ ์์ง๋ง ๋ด์ฉ์ด ์๋ "" ์ ๊ฒฝ์ฐ ๋ค๋ฅด๊ฒ ์ฒ๋ฆฌํฉ๋๋ค.
๋น ๊ฐ์ธ์ง ํ์ธํ๊ธฐ ์ํด์๋ isEmpty ์ ์ฌ์ฉํด์ ๋ง์ด ๋น๊ตํฉ๋๋ค. ํ์ง๋ง ๋ฌธ์ ๋ space ๊ฐ๋ ๊ฐ์ด ์๋ค๊ณ ํ๋จํฉ๋๋ค.
"Hello".isEmpty // false
"".isEmpty // true
" ".isEmpty // false
space ๊ณต๋ฐฑ์ผ๋ก ์ ํํด์ ๋น ๊ฐ์ผ๋ก ์ธ์ํ๊ธฐ
++์ถ๊ฐ ์์
๐ฅ ๋ฐ๋ผ์ nil๊ฐ์ธ์ง ๊ณต๋ฐฑ์ธ์ง ํ์ธํ๊ธฐ ์ํด ๋ฐ์ธ๋ฉ+isEmpty ์ฌ์ฉ
var optinalString: String?
if let result = optinalString, !optinalString!.isEmpty{
print("๊ฐ ์์")
}else{
print("๊ฐ ์์")
}
์ชผ๊ฐ์ ์ฌ์ฉํ๊ธฐ
var optinalString: String?
if let bindingString = optinalString{
if !bindingString.isEmpty{
print("๊ฐ ์์")
}else{
print("๋น ๊ฐ")
}
}else{
print("nil ๊ฐ")
}
*์ฐธ๊ณ ๋ก, String.count == 0 ์ฌ์ฉํ์ง ์๊ธฐ
// Don't do this to test for empty
myString.count == 0
'๐ iOS > Swift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Swift] ์ค์ํํธ ๋ฐ์ดํฐ ํ์ (Swift data type) - 2. ์ปฌ๋ ์ ํ์ (๋ฐฐ์ด(Array), ๋์ ๋๋ฆฌ(Dictionary), ์งํฉ(Set)) (1) | 2023.06.06 |
---|---|
[Swift] ๊ณ ์ฐจํจ์ - map, filter, reduce (0) | 2023.04.10 |
[Swift] ํจ์(Function) - ๊ณ ๊ธ (0) | 2022.03.12 |
[Swift] ํจ์(Function) - ๊ธฐ๋ณธ (0) | 2022.03.05 |
[Swift] ์ค์ํํธ ๋ฐ๋ณต๋ฌธ(Loops, Repetitive Statement) (0) | 2022.03.02 |