Programming/Swift(iOS)

Swift Optional - 2

홍열 2021. 4. 2. 21:34
728x90

이번시간에는 Optional을 활용하는 예제를 해보겠습니다. 

 

고객 등급을 나타내는 Membership enum이 있습니다.

 

struct User는 Membership을 Optional변수로 가지고 있습니다.

-> Membership이 있을 수도 있고, 없을 수도 있습니다. 

 

첫 객체는 .gold 정보가 있는 User이며, 두번째 객체는 nil을 가집니다.

이때 if let으로 정보를 가져오고, switch~case를 통해서 값을 출력해보면 현재 정보를 알 수 있습니다.

//멤버십 레벨을 나타내주는 enum
enum Membership {
    case gold
    case silver
}

//User는 멤버십을 가지고 있고, 이 멤버십은 있을수도 있고, 없을 수도 있습니다.
struct User {
    let membership:Membership?
}

//객체를 하나 만듭니다.
let user = User(membership: .gold)

if let membership = user.membership {
    switch membership {
    case .gold:
        print("gold 회원")
    case .silver:
        print("silver 회원")
    }
} else { //membership이 nil일 경우 여기로!
    print("멤버십 정보가 없음")
}


let user2 = User(membership: nil)
if let membership = user2.membership {
    switch membership {
    case .gold:
        print("gold 회원")
    case .silver:
        print("silver 회원")
    }
} else { //membership이 nil일 경우 여기로!
    print("멤버십 정보가 없음")
}

//결과 
//gold 회원
//멤버십 정보가 없음


//만약 if ~ let을 사용하기 싫으면..아래와 같이 사용하면 된다. 
//.gold? 가 가능한 이유는 User가 가진 membership 변수가 Optional이기 때문이다.

switch users.membership {
case .gold?: //gold인데 nil일수도 있어..nil이면 case nil로 가자
    print("10% 할인")
case .silver?:
    print("5% 할인")
case nil:
    print("0% 할인")
}

이번에는 Dictionary<String, Bool>을 가지고 해보겠습니다. 

//Dictionary<String, Bool> 예제
//JSON 파싱할때 사용하면 좋겠다.

let preference:[String:Bool] = [
    "autoLogin" : true,
    "isFaceIdEnabled" : true,
    "faceIdEnabled":true
]

if let autoLogin = preference["autoLogin"] {
    print(autoLogin) //true
}
//만약, preference에 없는 key로 접근을 한다면 ??

if let autoLogin = preference["abc"] {
    print(autoLogin)
} else {
    print("해당되는 key가 없다.")
}
/* 결과
true
해당되는 key가 없다.
*/

// Optional<Bool>은 3개의 값중에 하나를 가집니다.
// true, false, nil
// 내부적으로 값이 있을 때만 출력이 가능합니다. 

// "isFaceIdEnabled"을 가져와보고, 가져온 값이 true이면 "페이스 아이디 활성화"
if let isFaceIdEnabled = preference["isFaceIdEnabled"], isFaceIdEnabled {
	print("페이스 아이디 활성화 : \(isFaceIdEnabled)")
} else { //그 이외 모든 것은 비활성화이다.
	print("페이스 아이디 비활성화")
}

//위의 코드를 줄이는 방법은 nil 병합 연산
// preference["isFaceIdEnabled"]가 true, false인지는 상관안하고, 값이 nil인지 체크하고
// nil이면 ?? 다음 구문 실행한다.
// false를 얻기 위해서는 preference에 "isFaceIdEnabled" key 존재 자체가 없어야 한다.
if preference["isFaceIdEnabled"] ?? false {
    print("페이스 아이디 활성화")
} else {
    print("페이스 아이디 비활성화")
}


enum과 optional을 적절히 섞어서 사용하면 선택지를 만들 수 있습니다. 

UserPreference의 정보를  Preference의 key값의 여부에 따라서 관리하도록 만드는 예제입니다.

let preference:[String:Bool] = [
    "autoLogin" : true,
    "isFaceIdEnabled" : true,
    "faceIdEnabled":true
]

enum UserPreference:RawRepresentable {
    case enabled
    case disabled
    case notSet
    
    init(rawValue:Bool?) {
        switch rawValue {
        case true?:
            self = .enabled
        case false?:
            self = .disabled
        case nil:
            self = .notSet
        }
    }
    var rawValue:Bool? {
        switch self {
        case .enabled:
            return true
        case .disabled:
            return true
        case .notSet:
            return nil
        }
    }
}

let faceIdPref = UserPreference(rawValue: preference["faceIdEnabled"])

switch faceIdPref {
case .enabled:
    print("enabled")
case .disabled:
    print("disabled")
case .notSet:
    print("notSet")
}