2017-07-07 98 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