【发布时间】:2015-09-15 22:21:25
【问题描述】:
我正在尝试在 Swift 2 中为使用 NSUserDefaults 的任何类型的单一设置实现一个类。
问题:如何定义一个类来存储和检索任何类型的对象,包括Dictionary?
我有一个适用于 AnyObject 的解决方案,它由一个通用协议 (Settable) 和一个通用类 (Setting) 组成。 SettingsStore 是 NSUserDefaults 的包装。
// MARK: Settable Protocol
public protocol Settable {
typealias T
init(key: String, defaultValue: T, settingsStore: SettingsStore)
var value: T { get set }
func loadCurrentValue()
}
// MARK: Settings Class
public class Setting<T: AnyObject>: Settable {
private let key: String
private let defaultValue: T
private let settingsStore: SettingsStore
private var currentValue: T?
public required init(key: String, defaultValue: T, settingsStore: SettingsStore) {
self.key = key
self.defaultValue = defaultValue
self.settingsStore = settingsStore
}
public var value: T {
get {
if self.currentValue == nil {
self.loadCurrentValue()
}
return self.currentValue!
}
set {
self.currentValue = newValue
self.settingsStore.setObject(newValue.toAnyObject(), forKey: self.key)
}
}
public func loadCurrentValue() {
let optionalValue: T? = self.settingsStore.objectForKey(key) as? T
if let value = optionalValue {
self.currentValue = value
} else {
self.currentValue = self.defaultValue
}
}
}
这允许我创建这样的设置:
let specialId: Setting<String>
init() {
self.specialId = Setting<String>(
key: "specialId",
defaultValue: "<somevalue>",
settingsStore: self.settingsStore)
}
问题在于它不适用于值类型,例如 String、Bool、Int、Double、Array 或 Dictionary,因为它们都是值类型和值类型不符合AnyObject 协议。
我已经使用基于NSString 和NSNumber 的协议和扩展解决了其中一些问题,但是Dictionary 的解决方案被证明是难以捉摸的(我不需要@987654341 的解决方案@ 目前,所以我没有花时间尝试解决那个问题)。
// Change definition of Setting class like this:
public class Setting<T: AnyObjectRepresentable>: Settable {
...
}
public protocol AnyObjectRepresentable {
func toAnyObject() -> AnyObject
static func fromAnyObject(value: AnyObject) -> Self?
}
extension AnyObjectRepresentable where Self: AnyObject {
public func toAnyObject() -> AnyObject {
return self
}
public static func fromAnyObject(value: AnyObject) -> AnyObject? {
return value
}
}
extension String: AnyObjectRepresentable {
public func toAnyObject() -> AnyObject {
return NSString(string: self)
}
public static func fromAnyObject(value: AnyObject) -> String? {
let convertedValue = value as? String
return convertedValue
}
}
extension Bool: AnyObjectRepresentable {
public func toAnyObject() -> AnyObject {
return NSNumber(bool: self)
}
public static func fromAnyObject(value: AnyObject) -> Bool? {
let convertedValue = value as? Bool
return convertedValue
}
}
// Add extensions for Int and Double that look like the above extension for Bool.
我为Dictionary 尝试了两种不同的方法。第一个类似于String的方法:
extension Dictionary: AnyObjectRepresentable {
public func toAnyObject() -> AnyObject {
let value = self as NSDictionary
return value
}
public static func fromAnyObject(value: AnyObject) -> Dictionary? {
let convertedValue = value as? Dictionary
return convertedValue
}
}
Xcode 在toAnyObject() 方法实现的第一行给了我以下错误:
'Dictionary' 不能转换为 'NSDictionary'
接下来我尝试直接扩展NSDictionary:
extension NSDictionary: AnyObjectRepresentable {
public func toAnyObject() -> AnyObject {
return NSDictionary(dictionary: self)
}
public static func fromAnyObject(value: AnyObject) -> NSDictionary? {
let convertedValue = value as? NSDictionary
return convertedValue
}
}
Xcode 在fromAnyObject() 的声明中给出以下错误:
非最终类 'NSDictionary' 中的方法 'fromAnyObject' 必须返回 Self 以符合协议 'AnyObjectRepresentable'
我很机智。这可以解决吗?
谢谢,
大卫
2015-09-15 16:30 更新
作为背景,这里是SettingsStore的定义和实现:
public protocol SettingsStore {
func objectForKey(key: String) -> AnyObject?
func setObject(value: AnyObject?, forKey key: String)
func dictionaryForKey(key: String) -> [String:AnyObject]?
}
public class UserDefaultsSettingsStore {
private let userDefaults: NSUserDefaults
public init() {
self.userDefaults = NSUserDefaults.standardUserDefaults()
}
public init(suiteName: String) {
self.userDefaults = NSUserDefaults(suiteName: suiteName)!
}
}
extension UserDefaultsSettingsStore: SettingsStore {
public func objectForKey(key: String) -> AnyObject? {
return self.userDefaults.objectForKey(key)
}
public func setObject(value: AnyObject?, forKey key: String) {
self.userDefaults.setObject(value, forKey: key)
self.userDefaults.synchronize()
}
public func dictionaryForKey(key: String) -> [String : AnyObject]? {
return self.userDefaults.dictionaryForKey(key)
}
}
【问题讨论】:
-
不使用 AnyObject,使用 Any 怎么样?
-
关于您的错误,请查看Protocol fun returning Self。
-
我之前看过 - Rob Napier 关于这个主题的文章非常好,但不幸的是它在这种情况下对我没有帮助。
标签: swift dictionary swift2