Swift:清理声明/元编程

时间:2015-04-03 00:52:56

标签: swift refactoring metaprogramming

我有以下声明:

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行代码。

有没有一种清理这些声明的好方法?

我很乐意以这样的方式重构它,使每个声明成为一个内容 - 是否有某种方法可以用闭包来做到这一点?

1 个答案:

答案 0 :(得分:0)

到目前为止,我所拥有的解决方案并不像我想的那样光滑:

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"

我不相信这是一场大胜利。但它可能会得到它的好处。