我正在构建帮助程序以启用对NSUserDefaults
属性的类型化访问。像这样:
struct UserDefaults {
private static var standardUserDefaults: NSUserDefaults = {
return NSUserDefaults.standardUserDefaults()
}()
private static let propKey = "PROP"
static var prop: Bool {
get {
return standardUserDefaults.boolForKey(propKey)
}
set {
standardUserDefaults.setBool(newValue, forKey: propKey)
standardUserDefaults.synchronize()
}
}
}
这样我可以有一个很好的语法来读写NSUserDefaults
:
UserDefaults.prop // read
UserDefaults.prop = false // write
问题是这里有很多样板代码,每个aditional属性需要10行。
有没有办法减少每个新物业所需的线路数量?重用getter和setter?任何类型的运行时生成器?
答案 0 :(得分:1)
您可以尝试将实际值包装在一个处理所有脏工作的类中:
class WrappedUserDefault<T> {
let key : String
let defaultValue : T
var value : T {
get {
if let value = UserDefaults.standardUserDefaults.objectForKey(key) as? T {
return value
} else {
return defaultValue
}
}
set {
if let value = newValue as? AnyObject {
UserDefaults.standardUserDefaults.setValue(value, forKey: key)
} else {
UserDefaults.standardUserDefaults.removeObjectForKey(key)
}
UserDefaults.standardUserDefaults.synchronize()
}
}
init(key:String, defaultValue:T) {
self.key = key
self.defaultValue = defaultValue
}
}
struct UserDefaults {
static let standardUserDefaults = NSUserDefaults.standardUserDefaults()
static let ready = WrappedUserDefault<Bool>(key:"ready", defaultValue: true)
static let count = WrappedUserDefault<Int>(key: "count", defaultValue: 0)
}
然后只需要更多代码就可以了:
UserDefaults.count.value++
UserDefaults.ready.value = true
UserDefaults.ready.value
如果ready.value
的详细程度困扰你,你可以稍微隐藏一下,尽管那时你又回到了拥有相当数量的复制/粘贴代码的地方:
struct UserDefaults {
static let standardUserDefaults = NSUserDefaults.standardUserDefaults()
private static let readyWrapper = WrappedUserDefault<Bool>(key:"ready", defaultValue: true)
static var ready : Bool {
get { return readyWrapper.value }
set { readyWrapper.value = newValue }
}
}
至少在这种情况下,复制/粘贴代码相当简单,因此将来不太可能需要更改。
答案 1 :(得分:0)
我更喜欢大卫的答案,但这是另一种选择。将每个变量的10行减少到5(主要是因为删除了新的行...)
struct UserDefaults {
private static var standardUserDefaults: NSUserDefaults = {
return NSUserDefaults.standardUserDefaults()
}()
//Repeate these 5 lines for all new variables,
//changing the as? to the proper variable type
//Adding in a default value for the return in
//case the as? cast fails for any reason
private static let propKey = "PROP"
static var prop: Bool {
get { return (getVar(propKey) as? Bool) ?? false }
set { setVar(newValue, key:propKey) }
}
//The generic set/get
private static func getVar(key : String) -> AnyObject?
{
return standardUserDefaults.objectForKey(key)
}
private static func setVar(newValue : AnyObject, key : String)
{
if(newValue is Bool)
{
standardUserDefaults.setBool((newValue as? Bool)!, forKey: key)
}
//... More cases here
else if(newValue == nil)
{
standardUserDefaults.removeObjectForKey(key)
}
else
{
standardUserDefaults.setObject(newValue, forKey: key)
}
standardUserDefaults.synchronize()
}
}