我试图找出这两种方法之间的实际区别。例如:
struct PrimaryLabel: ViewModifier {
func body(content: Content) -> some View {
content
.padding()
.background(Color.black)
.foregroundColor(Color.white)
.font(.largeTitle)
.cornerRadius(10)
}
}
extension View {
func makePrimaryLabel() -> some View {
self
.padding()
.background(Color.black)
.foregroundColor(Color.white)
.font(.largeTitle)
.cornerRadius(10)
}
}
Run Code Online (Sandbox Code Playgroud)
然后我们可以按以下方式使用所有这些:
Text(tech.title)
.modifier(PrimaryLabel())
Text(tech.title)
.makePrimaryLabel()
ModifiedContent(
content: Text(tech.title),
modifier: PrimaryLabel()
)
Run Code Online (Sandbox Code Playgroud)
Moj*_*ini 17
你提到的所有方法都是正确的。不同之处在于您如何使用它以及访问它的位置。哪一个更好?是一个基于意见的问题,您应该查看干净的代码策略和 SOLID 原则等,以找到每种情况的最佳实践。
由于SwiftUI是非常修饰链基础,第二个选项最接近原始修饰符。你也可以像原件一样采用参数:
extension Text {
enum Kind {
case primary
case secondary
}
func style(_ kind: Kind) -> some View {
switch kind {
case .primary:
return self
.padding()
.background(Color.black)
.foregroundColor(Color.white)
.font(.largeTitle)
.cornerRadius(10)
case .secondary:
return self
.padding()
.background(Color.blue)
.foregroundColor(Color.red)
.font(.largeTitle)
.cornerRadius(20)
}
}
}
struct ContentView: View {
@State var kind = Text.Kind.primary
var body: some View {
VStack {
Text("Primary")
.style(kind)
Button(action: {
self.kind = .secondary
}) {
Text("Change me to secondary")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我们应该拭目以待,看看此类新技术的最佳实践是什么。我们现在发现的任何东西都只是一个好习惯。
我相信最好的方法是将 ViewModifiers 和 View 扩展结合起来。这将允许在 ViewModifier 中组合 @State 并方便 View 扩展。
struct PrimaryLabel: ViewModifier {
func body(content: Content) -> some View {
content
.padding()
.background(Color.black)
.foregroundColor(Color.white)
.font(.largeTitle)
.cornerRadius(10)
}
}
extension View {
func makePrimaryLabel() -> some View {
ModifiedContent(content: self, modifier: PrimaryLabel())
}
}
Run Code Online (Sandbox Code Playgroud)
用法
Text(tech.title)
.makePrimaryLabel()
Run Code Online (Sandbox Code Playgroud)
我通常更喜欢扩展,因为它们可以为您提供更具可读性的代码,并且编写起来通常更短。实际上,我目前正在撰写带有一些技巧的文章。我完成了一篇关于View扩展的文章,可在此处获得。
但是,存在差异。最后一个。使用ViewModifier,您可以使用@State变量,但不能使用View扩展名。这是一个例子:
struct ContentView: View {
var body: some View {
VStack {
Text("Hello, how are you?").modifier(ColorChangeOnTap())
}
}
}
struct ColorChangeOnTap: ViewModifier {
@State private var tapped: Bool = false
func body(content: Content) -> some View {
return content.foregroundColor(tapped ? .red : .blue).onTapGesture {
self.tapped.toggle()
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用 ViewModifier 时,结果视图的类型签名可能有优势。例如,如果我们创建以下 TestView 来显示三个变体的类型:
struct TestView: View {
init() {
print("body1: \(type(of: body))")
print("body2: \(type(of: body2))")
print("body3: \(type(of: body3))")
}
@ViewBuilder var body: some View {
Text("Some Label")
.modifier(PrimaryLabel())
}
@ViewBuilder var body2: some View {
Text("Some Label")
.makePrimaryLabel()
}
@ViewBuilder var body3: some View {
ModifiedContent(
content: Text("Some Label"),
modifier: PrimaryLabel()
)
}
}
Run Code Online (Sandbox Code Playgroud)
我们可以看到它产生以下类型:
body1: ModifiedContent<Text, PrimaryLabel>
body2: ModifiedContent<ModifiedContent<ModifiedContent<ModifiedContent<ModifiedContent<Text, _PaddingLayout>, _BackgroundStyleModifier<Color>>, _EnvironmentKeyWritingModifier<Optional<Color>>>, _EnvironmentKeyWritingModifier<Optional<Font>>>, _ClipEffect<RoundedRectangle>>
body3: ModifiedContent<Text, PrimaryLabel>
Run Code Online (Sandbox Code Playgroud)
即使在执行过程中没有优势,它也可能使调试变得更容易。
| 归档时间: |
|
| 查看次数: |
307 次 |
| 最近记录: |