import Foundation

//dynamicMemberLookup_keyPath
struct Address {
    let street: String
    let zipCode: String
    let city: String
}

@dynamicMemberLookup
struct Person {
    let firstName: String
    let lastName: String
    private let address: Address

    init(firstName: String, lastName: String, address: Address) {
        self.firstName = firstName
        self.lastName = lastName
        self.address = address
    }
    
    subscript<T>(dynamicMember keyPath: KeyPath<Address, T>) -> T {
        self.address[keyPath: keyPath]
    }

}

let address = Address(street: "青岛街", zipCode: "266700", city: "北京市")
let person = Person(firstName: "五", lastName: "王", address: address)
print(person.firstName)

//property_wrappers
//https://www.avanderlee.com/swift/property-wrappers/
extension UserDefaults {
    
    public enum Keys {
        static let hasSeenAppIntroduction = "has_seen_app_introduction"
    }
    
    var hasSeenAppIntroduction: Bool {
        set {
            set(newValue, forKey: Keys.hasSeenAppIntroduction)
        }
        get {
            bool(forKey: Keys.hasSeenAppIntroduction)
        }
    }
}

UserDefaults.standard.hasSeenAppIntroduction = true
print(UserDefaults.standard.hasSeenAppIntroduction)

@propertyWrapper
struct UserDefault<T> {
    let key: String
    let defaultValue: T
    
    init(_ key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }
    
    var value: T {
        get {
            UserDefaults.standard.value(forKey: key) as? T ?? defaultValue
        }
        set {
            UserDefaults.standard.set(newValue, forKey: key)
        }
    }
}

struct UserDefaultsConfig {
    @UserDefault("has_seen_app_introduction", defaultValue: false)
    static var hasSeenAppIntroduction: Bool
}

print(UserDefaultsConfig.hasSeenAppIntroduction)

--EOF--