2017-07-07 45 views
2

我想实现这样的属性,它的值只能读取一次,然后属性应设置为nil只读一次,然后设置为零

我在这样的方式来实现它:

private var _readOnce: String? 

var readOnce: String? { 
    get { 
     let value = _readOnce 
     _readOnce = nil 
     return value 
     } 
    set { 
     _readOnce = newValue 
    } 
} 

readOnce = "Andrej" 

print("read once = \(readOnce)") // prints read once = Optional("Andrej")\n" 
print("read once = \(readOnce)") // prints read once = nil\n" 

但I'feel就像使用一个单独的属性_readOnce不是“SWIFTY” /“最优雅”的方式来做到这一点。

有谁知道一种不同的方式,那将不需要使用单独的属性?

我可以确认上面的代码有效,只是我觉得它可以更优雅,更少的线条来实现相同的行为。

+1

好奇......你为什么要这么做? – Honey

+0

我以为我可以使用这种方法来反应推送通知,并确保我只反应一次。所以我一直在探索这种方法。但是现在看来,我必须采取不同的方法,因为其他一些事情的行为并不像我期望的那样。 – Andrej

+1

我不知道你的问题的确切问题。但是我正在考虑多种其他方式来解决这个问题1.只需要布尔属性* somewhere * 2.在iOS 10中,不同的委托方法使得管理你想要的更容易。这就是说,如果你的通知有'content-available:1',那么你的应用程序(_:didReceiveRemoteNotification:fetchCompletionHandler :)会被调用。如果用户点击通知“didreceivenotificationresponse”将被调用。如果用户在应用程序中,将会调用'willPresentNotification'。 – Honey

回答

2

我不知道有一种方法可以避免拥有支持属性,但我可能会做的是做一个帮手类型来包装行为。事情是这样的:

struct OneTimeValue<T> 
{ 
    private var isUnread = true 

    private let value : T 

    init(_ value: T) 
    { 
     self.value = value 
    } 

    func get() -> T? 
    { 
     guard isUnread else { 
      return nil 
     } 
     self.isUnread = false 
     return self.value 
    } 
} 

你也可以,如果你喜欢写这有点不同,由nil玲出valueget()内,例如,但总体规划成立。

然后你的类就变成了:

class Miser 
{ 
    var readOnce : String? 
    { 
     return self._readOnce.get() 
    } 
    private let _readOnce = OneTimeValue("Can't touch this (twice)") 
} 

我也用这种模式的UserDefaultsValue(存储到/从用户默认)和SynchronizedValue(一个属性读写锁),我认为这效果很好。

1

据我所知,没有第二个变量是不可能的。这是因为计算的属性不存储任何数据为它们所代表的变量:

除了存储性能,类,结构和 枚举可以定义计算的性质,这实际上并不 存储的值。

对于非计算的属性,你可以拥有的唯一观察员基于变量的设置,而不是获取(即willSetdidSet

希望帮助!

编辑: 它可以关闭和财产观察家如果你细心的话来完成: 这不需要其他变量(而不是值由封闭拍摄的),但它是相当不明确 - 我不会推荐它。

var readOnce:() -> String? = {nil} { 
    didSet{ 
     readOnce = { [weak self, readOnce] in 
      self?.readOnce = {nil} 
      return readOnce() 
     } 
    } 
} 

readOnce()  // returns nil 
readOnce = {"Hi"} 
readOnce()  // returns optional wrapped "Hi" 
readOnce()  // returns nil 

更多的“SWIFTY”为你解答:d

+0

'didSet'在你的第一个* set之后*不在你的第一个* get *之后* /读 – Honey

+0

@Honey是,同意 - 但是这个解决方案是基于在'readOnce'被设置之后将值更改为闭包的想法。 **然后在读取变量**时执行此闭包,并将readOnce重置为{nil},以使其不能被读取两次。上面的代码工作,但同样,由于涉及hackery,我不会推荐。 –

+0

当然,非常有趣的方法,学到了新的东西。 :)也同意你的看法,这是一种黑客行为,不会在其他开发者的项目中使用,因为它不能立即清楚发生了什么。 – Andrej