Swift中对UserDefaults的封装

Founddation中UserDefaults是一种很轻量化的本地化工具,实际开发中经常会使用,由于苹果中很多类库还没有用Swift重写,所以在Swift中用UserDefaults就显示不是很Swift,还是OC的感觉,所以我就想对UserDefaults进行一次封装,让它更Swift,用起来更方便.我最早由这种想法实在Swift2的时候,那时候就感觉用起来不是很方便了,但是没有多想,之后又看到了一篇文章传送门,它是用Swift中subscript的方法对NSUserDefaults进行了封装,Swift中,Dic[key],Array[index],都是使用了subscript方法.我就是参照这位外国友人的思路进行了封装.

[subscript] + 泛型 的方式

这是我最开始的设计思路,先看代码

protocol UserDefaultProtocol {
    func getKey() -> String
}
enum DefaultsKey: String,UserDefaultProtocol {
    case token
    case name
    case mobile
    func getKey() -> String {
        return self.rawValue
    }
}
public let Defaults = UserDefaults.standard
extension UserDefaults {
    
    subscript(key: UserDefaultProtocol) -> Fakegenericity {
        return Fakegenericity(self, key.getKey())
    }
    subscript(key: UserDefaultProtocol) -> Any?{
        get{
            let genericity : Fakegenericity = self[key]
            return genericity
        }
        set{
            guard let newValue = newValue else {
                removeObject(forKey: key.getKey())
                return
            }
            switch newValue {
            case let v as Double:
                self.set(v, forKey: key.getKey())
            case let v as Int:
                self.set(v, forKey: key.getKey())
            case let v as Bool:
                self.set(v, forKey: key.getKey())
            case let v as URL:
                self.set(v, forKey: key.getKey())
            default:
                self.set(newValue, forKey: key.getKey())
            }
        }
    }
    ///直接根据key取int  double等  就算取不到  也会返回 0  当有要存储0的需求时候  会有问题  所以 用过根据 object 去数据转 nsnumer  判断number?  使取 bool int等类型时  没有值会返回nil
    func numberForKey(_ key: String) -> NSNumber? {
        return object(forKey: key) as? NSNumber
    }
    
    /// Returns `true` if `key` exists
    func hasKey(key: UserDefaultProtocol) -> Bool {
        return object(forKey: key.getKey()) != nil
    }
    
    func removeAll(){
        for(key,_) in dictionaryRepresentation() {
            removeObject(forKey: key)
        }
    }
    func remove(key: UserDefaultProtocol){
        removeObject(forKey: key.getKey())
    }
    class Fakegenericity {
        fileprivate let defaults: UserDefaults
        fileprivate let key: String
        
        fileprivate init(_ defaults: UserDefaults, _ key: String) {
            self.defaults = defaults
            self.key = key
        }
        
        // MARK: only - get
        public var object: Any? {
            return defaults.object(forKey: key)
        }
        
        public var string: String? {
            return defaults.string(forKey: key)
        }
        
        public var array: [Any]? {
            return defaults.array(forKey: key)
        }
        
        public var dictionary: [String: Any]? {
            return defaults.dictionary(forKey: key)
        }
        
        public var data: Data? {
            return defaults.data(forKey: key)
        }
        
        //        public var date: Date? {
        //            return object as? Date
        //        }
        
        public var number: NSNumber? {
            return defaults.numberForKey(key)
        }
        
        public var int: Int? {
            return number?.intValue
        }
        
        public var double: Double? {
            return number?.doubleValue
        }
        
        public var bool: Bool? {
            return number?.boolValue
        }
        
        
        public var stringValue: String {
            return string ?? ""
        }
        
        public var arrayValue: [Any] {
            return array ?? []
        }
        
        public var dictionaryValue: [String: Any] {
            return dictionary ?? [:]
        }
        
        public var dataValue: Data {
            return data ?? Data()
        }
        
        public var intValue: Int {
            return int ?? 0
        }
        
        public var doubleValue: Double {
            return double ?? 0
        }
        
        public var boolValue: Bool {
            return bool ?? false
        }
    }
}