簡體   English   中英

如何在協議擴展中存儲提交到計算屬性的數據?

[英]How do I store data submitted to computed properties in a protocol extension?

在我目前正在開發的應用程序中,我嘗試利用Swift中的新協議擴展功能。 我的想法是我有很多類實現相同的協議。 由於所有這些類都應該具有相同的計算屬性,並且由於屬性在不同的類中應該表現相同,所以我認為僅添加一次功能會很好。

我的代碼結構如下

protocol SomeProtocol { ... }

// There could potentially be unlimited different versions of "SomeClass" that implements "SomeProtocol"
class SomeClass : SomeProtocol { ... }

extension SomeProtocol {
    var computedProperty1: Type? {
        get { getData(SOME_ENUM) }
        set { validateAndSave(newValue, atKey: SOME_ENUM) }
    }
    var computedProperty2: Type? {
        get { getData(SOME_OTHER_ENUM) }
        set { validateAndSave(newValue, atKey: SOME_OTEHR_ENUM) }
    }
    ...

    func getData(atKey: ENUM_TYPE) -> Type? {
        [NEED SOME WAY TO GET THE SAVED DATA AND RETURN IT]
    }
    func validateAndSave(value: Type?, atKey: ENUM_TYPE) {
        [NEED SOME WAY TO SAVE DATA FOR LATER RETURNING]
    }
}

// The properties needs to be visible to the client code like this:
class ClientCode {
    let someClassObject: SomeProtocol = SomeClass()
    someClassObject.computedProperty1 = Type()
    print(someClassObject.computedProperty1)
}

(上面的代碼顯示了將數據存儲在不同字典中的跡象,這是我的第一個想法)

問題是擴展不支持存儲的屬性。 但是,我在哪里/如何存儲提交給計算屬性的數據呢?

我可以想到兩種不同的解決方案,但它們都不好......

  1. 我可以將擴展轉換為實現SomeProtocol的類,然后使SomeClass成為它的子類。 這將允許我將數據保存在存儲的屬性中。 但是它還需要我實現協議在新類中所需的所有方法 - 這絕對沒有意義,因為SomeClass的不同版本應該提供不同的功能。
  2. 我可以放棄整個擴展的想法,並將所有屬性移動到SomeProtocol 但這需要我在具有相同功能的SomeClass所有不同版本中實現所有計算屬性,並且我的擴展想法的重點是避免一遍又一遍地為相同的屬性編寫相同的實現。

是否有一些我忽略的完全簡單的邏輯解決方案?

...或者在我不知道的協議擴展中保存數據的好方法?

...或獲得所需功能的其他方式?

...或者我應該把它吸干並使用我不那么漂亮的解決方案之一?

假設我正確地理解了這個問題,以解決協議擴展不支持存儲屬性這一事實,您可以擴展NSObject並使用目標C運行時來存儲您的屬性。

import ObjectiveC

private var AssociationKey: UInt8 = 0

class YourStoredObject {
  // Whatever object your are persisting
}

extension NSObject {
  var yourStoredObject: (YourStoredObject)! {
    get {
      return objc_getAssociatedObject(self, &AssociationKey) as? YourStoredObject
    }
    set(newValue) {
      objc_setAssociatedObject(self, &AssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
    }
  }
}

protocol YourProtocol {
  var yourStoredObject: YourStoredObject! { get set }
}

extension YourProtocol {

  func customYourStoredObjectGetter() -> YourStoredObject {
    return yourStoredObject
  }

}

extension UILabel : YourProtocol {

  func myExtendedFunc() {
    // Get (and print) your object directly
    print(yourStoredObject)
    // Get your object through a protocol custom getter
    print(customYourStoredObjectGetter())

    // Set your object
    yourStoredObject = YourStoredObject()
  }
}

我不是說這是最好的解決方案,但這是我能想到的唯一解決方案。 我也在尋找更好的Swift替代品,但仍未找到任何替代品。

協議擴展? 為什么?

有時我們會這么想,以至於我們忽略了一種盯着我們的實際解決方案。

你有一組計算屬性嗎? 不,您想要存儲的屬性。

由於所有這些類都應該具有相同的計算屬性,並且因為屬性在不同的類中的行為應該相同...

... 但后來

問題是擴展不支持存儲的屬性。 但是,我在哪里/如何存儲提交給計算屬性的數據呢?

2.假設它是您想要的一組存儲屬性,您實際上自己提供了解決方案! 做了一個現在有意義的改變。

我可以將擴展轉換為實現SomeProtocol的類然后使SomeClass成為它的子類。 這將允許我將數據保存在存儲的屬性中。

您可以隨時擴展該類, 然后將其子類確認為SomeProtocol以獲取這些功能。 這比較干凈。

另一方面,Swift的協議無法存儲屬性是設計的。 協議本身並不存在,並且在其中添加存儲的屬性是沒有意義的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM