오늘은 Any
와Optional
에 대해서 포스팅하려 한다.
Swift 공식 문서에서
Any
는 함수타입을 포함하여 모든 타입의 인스턴스를 나타낼 수 있다고 한다.
Any
는 평소에 잘 안 쓰지만, 보통 서버와 통신을 위해 parameter를 [String : Any]
로 하는 경우가 많다.
Optional
에 대해서는 여기에서 한 번 다뤘었다.
Optional
은 어떠한 변수에 값이 있을 수도 없을 수도 있는 경우를 위해 사용한다.
Optional
은 제네릭과 enum의 조합으로 이뤄져 있다.
Optional
은 아래와 같은 2가지 케이스로 이뤄져 있다.
public enum Optional<Wrapped> : ExpressibleByNilLiteral {
case none
case some(Wrapped)
print init(_ some: Wrapped)
...
}
(Jake🙇♂️)
이 포스팅을 쓰게된 이유는 아래와 같다.
[String : Any]
타입의 parameter를 구성했다.Any
타입인 value에 Optional
값이 들어가는 필드가 있었다.URLBody
를 구성할때 value가 nil
인 경우와 아닌 경우를 분기를 태워야 했다.위의 상황을 아래 코드 예시로 확인해보자.
struct TestParameter {
let a: Int
let b: Bool
let c: Int?
}
let testParameter = TestParameter(a: 1, b: true, c: nil)
let test: [String : Any] = [
"a" : testParameter.a,
"b" : testParameter.b,
"c" : testParameter.c
]
Optional
프로퍼티를 갖도록 struct를 선언했다.
[String : Any]
타입을 갖는 test 프로퍼티를 선언했다.
nil
인 필드를 확인하기 위해서 어떻게 해야할까?for (key, value) in test {
if value == nil {
print("this is nil")
} else {
print("\(key) : \(value)")
}
}
if문을 이용해 value가 nil
인 값을 확인했다.
c : nil
a : 1
b : true
내 생각과 다르게 if문을 거치지 않고 위와 같이 출력되었다.
한 번 확인해보자!
let testInt: Int? = nil
let testAny: Any = testInt as Any
print(type(of: testAny))
// 출력
Optional<Int>
Optional
은 아래와 같이 제네릭과 enum으로 이뤄져 있다.
public enum Optional<Wrapped> : {}
Optional<Int>
로 출력된 이유는 testAny 프로퍼티는 Int
타입을 받는 Optional
이라는 enum 타입이라는 얘기이다.
Optional
은 데이터가 있을때는 case some
을 갖고, nil일때는 case none
을 갖는다.
Any
타입은 모든 타입의 인스턴스를 나타낼 수 있다.
let testIntNone = Optional<Int>.none
let testIntNil: Int? = nil
print(testIntNone)
print(testIntNil)
// 출력
nil
nil
즉, testIntNone
, testIntNil
이 같은 의미이다.
let testIntSome = Optional<Int>.some(1)
let testIntOptionalValue: Int? = 1
print(testIntSome)
print(testIntOptionalValue)
// 출력
Optional(1)
Optional(1)
즉, testIntSome
, testIntOptionalValue
가 같은 의미이다.
위의
TestParameter
로 돌아가보자.
그렇다면let test: [String : Any]
의 c의 value에는nil
이 아닌Optional<Int>.none
이 저장되었음을 알 수 있다.
for (key, value) in test {
if case Optional<Any>.none = value {
print("this is nil")
} else {
print("\(key) : \(value)")
}
}
value가 Optional
의 enum case 인스턴스인지 확인했다.
this is nil
a : 1
b : true
나는 [String : Any]
로 변환하기 전에 nil
인지 아닌지 확인한 후 변환을 선호해서 위와 같은 상황을 이번에 처음 봤다ㅋㅋㅋ
그래도 왜 그랬는지 알고 나니 전에 다뤘던 내용과 관련도 있고, 재밌어서 글로 남겨봤다.
그럼 이만👋