0

考虑 SwiftUI 中的以下扩展:

extension Text{
   func applyBG() -> some View {
      self
         .padding(20)
         .background(Color(hue: 0, saturation: 0, brightness: 0.22).cornerRadius(10))
         .foregroundColor(.white)
   }
}

extension TextField{
   func applyBG() -> some View {
      self
         .padding(20)
         .background(Color(hue: 0, saturation: 0, brightness: 0.22).cornerRadius(10))
         .foregroundColor(.white)
   }
}

我觉得我可以写得更好,避免重复。我可能可以通过以下方式解决这个问题:

extension View{
   func applyBG() -> some View {
      self
         .padding(20)
         .background(Color(hue: 0, saturation: 0, brightness: 0.22).cornerRadius(10))
         .foregroundColor(.white)
   }
}

但我不希望我所有的观点都能够调用这个方法。我只希望 Text 和 Textfield 有这样的方法。我尝试使用协议和关联类型,但我无法一次编写这些行以实现干净的代码。关于我如何实现 DRY 的任何提示或伪代码?

4

2 回答 2

5

使用这样的协议:

import SwiftUI

protocol BGApplyable where Self: View {}

extension BGApplyable {
  func applyBG() -> some View {
    self
     .padding(20)
     .background(Color(hue: 0, saturation: 0, brightness: 0.22).cornerRadius(10))
     .foregroundColor(.white)
  }
}

决定哪些视图可以采用该协议:

extension TextField: BGApplyable {}
extension Text: BGApplyable {}

然后使用它:

var body: some View {
  VStack {
    Text("Foo")
      .applyBG()
    TextField("Hello", text: .constant("World!"))
      .applyBG()
  }
}
于 2021-03-03T10:52:27.653 回答
2

您可以在协议上声明该函数,只需将其返回类型从 更改some ViewAnyView,然后制作TextTextField符合该协议。

protocol TextView: View {
    func applyBackground() -> AnyView
}

extension TextView {
    func applyBackground() -> AnyView {
        AnyView(padding(20)
                    .background(Color(hue: 0, saturation: 0, brightness: 0.22).cornerRadius(10))
                    .foregroundColor(.white)
        )
    }
}

extension Text: TextView {}
extension TextField: TextView {}

Text("text").applyBackground()
于 2021-03-03T10:48:50.133 回答