2017-02-26 21 views
1

我有許多類都具有borderColor屬性。我可以在故事板中的用戶定義屬性中設置此屬性,然後使用一個單獨的UIView擴展名來實際添加邊框和它的顏色。很棒。在Swift中消除重複的「用戶定義運行時屬性」代碼

但是我對每個子類申報「BORDERCOLOR」屬性。協議擴展和擴展都不允許我聲明這種計算屬性,所以我可以在我的所有子類中使用它。

我有很多其他類和許多其他屬性,如borderWidth,shadowColor等,所以它最終是一個大量的重複代碼。

並且每個子類都需要繼承特定的超類,即UIImageView,而不僅僅是UIView,因爲在下面的示例中還有其他方法未詳細說明。所以我不能將這些添加到一些UIView子類中,然後讓所有這些類繼承它。

,我怎麼可能會降低所有我的項目中重複的屬性有什麼想法?

謝謝!

class BDRImageView: UIImageView { 
    var borderColor: UIColor? { 
     willSet { 
      if let color = newValue { 
       addBorder(color: color) 
      } 
     } 
    } 
} 

class BDRLabel: UILabel { 
    var borderColor: UIColor? { 
     willSet { 
      if let color = newValue { 
       addBorder(color: color) 
      } 
     } 
    } 
} 

class BDRButton: UIButton { 
    var borderColor: UIColor? { 
     willSet { 
      if let color = newValue { 
       addBorder(color: color) 
      } 
     } 
    } 
} 

//and so on... 

extension UIView { 
    func addBorder(color: UIColor) { 
     //does add border stuff... 
    } 
} 

回答

1

您可以利用目標C運行時功能的關聯對象的自定義屬性的類別添加到現有的類

extension UIView { 

    private struct customProperties { 
     static var borderColor: UIColor = .clear 
    } 

    var borderColor: UIColor? { 
     get { 
      return objc_getAssociatedObject(self, 
            &customProperties.borderColor) as? UIColor 
     } 
     set { 
      if let color = newValue { 
       objc_setAssociatedObject(self, 
          &customProperties.borderColor, 
          color, 
          .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 
       // Do whatever you want to do with color 
      } 
     } 
    } 
} 
6

您可以通過在協議宣佈的計算特性,然後創建它採用的是協議的每個子類的擴展,降低你的代碼。例如,您目前的代碼可以簡化爲:

protocol BorderColorSettable {} 
extension BorderColorSettable where Self: UIView { 
    var borderColor: UIColor? { 
     get { 
      //you will have to supply something here 
     } 
     set { 
      if let color = newValue { 
       self.addBorder(color: color) 
      } 
     } 
    } 
} 

extension UIImageView: BorderColorSettable {} 
extension UILabel: BorderColorSettable {} 
extension UIButton: BorderColorSettable {} 

extension UIView { 
    func addBorder(color: UIColor) { 
     //does add border stuff... 
    } 
} 

即使如此,你可以把執行的協議去掉UIView約束

extension BorderColorSettable { 
    var borderColor: UIColor? { 
     get { 
      //you will have to supply something here 
     } 
     set { 
      if let color = newValue { 
       self.addBorder(color: color) 
      } 
     } 
    } 

    func addBorder(color: UIColor) { 
     //does add border stuff... 
    } 
} 

的概念基本上是這樣的:聲明一個協議與你想要的功能。創建一個現有類的擴展(例如UIImageView),它只能採用該協議。然後這提供了UIImageView的所有實例與該協議的功能。

如果你給我一點時間,我可以在一個測試項目中運行它,以確保它可以開箱即用。否則,你可以嘗試自己調整它。

編輯:我拋出這個變成一個小項目,它似乎工作得很好。例如,實現所有的代碼後,我能夠運行一些操作是這樣的:

let label = UILabel() 
label.addBorder(color: .black) 

var label = UILabel() 
label.borderColor = .black 

希望這滿足你的需求。讓我知道我是否可以更徹底地解釋它的任何部分。

+0

這是一個偉大的答案,我不知道我還可以使用'GET'和'set'在協議擴展中,即使我不能使用'willSet'。但是,當我將屬性移動到擴展時,它通過故事板中用戶定義的運行時屬性設置屬性時永遠不會被調用。 – Frankie

+0

嗯,我從來沒有嘗試過。我不太清楚故事板運行時屬性背景中發生的情況。這很有趣,我想看看它:)也許我可以稍後@Frankie回來一些有用的信息 –

相關問題