Swift:清理declarations/meta编程
Swift: clean up declarations/meta programming
我有以下声明:
var loginServiceUsed: String? = NSUserDefaults.standardUserDefaults().stringForKey(Constants.loginServiceUsed.rawValue) {
didSet {
NSUserDefaults.standardUserDefaults().setObject(loginServiceUsed, forKey: Constants.loginServiceUsed.rawValue)
}
}
var loginServiceToken: String? = NSUserDefaults.standardUserDefaults().stringForKey(Constants.loginServiceToken.rawValue) {
didSet {
NSUserDefaults.standardUserDefaults().setObject(loginServiceToken, forKey: Constants.loginServiceToken.rawValue)
}
}
...
重复了大约六次。这么多相同的模式让我有点反胃。如果我正在编写 ruby 代码,我会在其中放置一点元编程,它将是一个变量名数组和相关的 4-5 行它们所做的一切 - 我会失望的到 6 行代码。
有没有清理这些声明的好方法?
我很乐意以这样一种方式重构它,使每个声明成为一个衬里 - 有什么方法可以用闭包来做到这一点吗?
到目前为止,我的解决方案并没有我想要的那么巧妙:
struct BackedVariable<type: AnyObject> {
var key: String
init(_ key: String) {
self.key = key
}
var value: type? {
set {
NSUserDefaults.standardUserDefaults().setObject(newValue, forKey: key)
}
get {
let returnValue = NSUserDefaults.standardUserDefaults().objectForKey(self.key) as? type
return returnValue
}
}
}
var bv: BackedVariable = BackedVariable<NSString>("backed")
bv.value = "foo"
println("\(bv.value!)") // "foo"
所以
var loginServiceUsed: BackedVariable<String>("loginServiceUsed")
loginServiceUsed.value = "SomeValue"
doSomethingWith(loginServiceUsed.value)
这并不可怕,但这不是我所希望的。我无法重写 = 运算符来进行更自然的赋值。我正在考虑添加一些其他运算符,这样我就可以做到
loginServiceUser <operator assigns> newValue
它封装了重复的复杂性,所以这很好。
稍后...
我可以加
postfix operator & { }
postfix operator &! { }
func &=<type: AnyObject>(inout oldValue:BackedVariable<type>, newValue: type?) -> BackedVariable<type> {
oldValue.value = newValue
return oldValue
}
postfix func &<type>(object: BackedVariable<type>) -> type? {
return object.value
}
postfix func &!<type>(object: BackedVariable<type>) -> type {
return (object&)!
}
然后
loginServiceUser &= "bar"
println("\(loginServiceUser.value!)") // "bar"
println("\((loginServiceUser&)!)") // "bar"
println("\(loginServiceUser&!)") // "bar"
我不认为这是一个巨大的胜利。但它可能和它会得到的一样好。
我有以下声明:
var loginServiceUsed: String? = NSUserDefaults.standardUserDefaults().stringForKey(Constants.loginServiceUsed.rawValue) {
didSet {
NSUserDefaults.standardUserDefaults().setObject(loginServiceUsed, forKey: Constants.loginServiceUsed.rawValue)
}
}
var loginServiceToken: String? = NSUserDefaults.standardUserDefaults().stringForKey(Constants.loginServiceToken.rawValue) {
didSet {
NSUserDefaults.standardUserDefaults().setObject(loginServiceToken, forKey: Constants.loginServiceToken.rawValue)
}
}
...
重复了大约六次。这么多相同的模式让我有点反胃。如果我正在编写 ruby 代码,我会在其中放置一点元编程,它将是一个变量名数组和相关的 4-5 行它们所做的一切 - 我会失望的到 6 行代码。
有没有清理这些声明的好方法?
我很乐意以这样一种方式重构它,使每个声明成为一个衬里 - 有什么方法可以用闭包来做到这一点吗?
到目前为止,我的解决方案并没有我想要的那么巧妙:
struct BackedVariable<type: AnyObject> {
var key: String
init(_ key: String) {
self.key = key
}
var value: type? {
set {
NSUserDefaults.standardUserDefaults().setObject(newValue, forKey: key)
}
get {
let returnValue = NSUserDefaults.standardUserDefaults().objectForKey(self.key) as? type
return returnValue
}
}
}
var bv: BackedVariable = BackedVariable<NSString>("backed")
bv.value = "foo"
println("\(bv.value!)") // "foo"
所以
var loginServiceUsed: BackedVariable<String>("loginServiceUsed")
loginServiceUsed.value = "SomeValue"
doSomethingWith(loginServiceUsed.value)
这并不可怕,但这不是我所希望的。我无法重写 = 运算符来进行更自然的赋值。我正在考虑添加一些其他运算符,这样我就可以做到
loginServiceUser <operator assigns> newValue
它封装了重复的复杂性,所以这很好。
稍后...
我可以加
postfix operator & { }
postfix operator &! { }
func &=<type: AnyObject>(inout oldValue:BackedVariable<type>, newValue: type?) -> BackedVariable<type> {
oldValue.value = newValue
return oldValue
}
postfix func &<type>(object: BackedVariable<type>) -> type? {
return object.value
}
postfix func &!<type>(object: BackedVariable<type>) -> type {
return (object&)!
}
然后
loginServiceUser &= "bar"
println("\(loginServiceUser.value!)") // "bar"
println("\((loginServiceUser&)!)") // "bar"
println("\(loginServiceUser&!)") // "bar"
我不认为这是一个巨大的胜利。但它可能和它会得到的一样好。