将视图提取到函数或结构中?

Pet*_*Pan 4 swift swiftui

我刚开始学习 Swift 和 SwiftUI。我有一个带有视图的结构,其中包含 VStack。在 VStack 中,我调用了四个返回视图的函数。

var body: some View {
    VStack {
        
        self.renderLogo()
        self.renderUserNameTextField()
        self.renderPasswordSecureField()
        self.renderLoginButton()
        
    }
}

func renderLoginButton() -> some View {
    return Button(action: {print("Button clicked")}){
        Text("LOGIN").font(.headline).foregroundColor(.white).padding().frame(width: 220, height: 60).background(Color(red: 0, green: 70/255, blue: 128/255)).cornerRadius(15.0)
    }.padding()
}[...]
Run Code Online (Sandbox Code Playgroud)

我刚刚读到,将视图提取到这样的结构中更为常见:

struct UsernameTextField : View {
@Binding var username: String
var body: some View {
return TextField("Username", text: $username)
            .padding()
            .background(lightGreyColor)
            .cornerRadius(5.0)
            .padding(.bottom, 20)
    }
}
Run Code Online (Sandbox Code Playgroud)

这是为什么?使用结构体代替普通函数有什么优点?

Abi*_*ern 5

这提出了一个有趣的观点。您不想通过使用带有大量修饰符的标准控件来创建大型视图,但您想要某种重用,可以通过使用返回视图的函数或自定义视图。

当我在 SwiftUI 中遇到这些问题时,我会查看我正在提取的内容。在您的情况下,控件看起来像是标准的,但它们应用了不同的样式。线索就在所有函数的名称中render

在这种情况下,我不会使用函数或自定义视图,而是编写一个自定义修饰符,将一组常见样式应用于控件。您的代码中的几个示例:

首先,创建ViewModifiers

struct InputTextFieldModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(Color.gray)
            .cornerRadius(5.0)
            .padding(.bottom, 20)
    }
}


struct ButtonTextModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.headline)
            .foregroundColor(.white)
            .padding()
            .frame(width: 220, height: 60)
            .background(Color(red: 0, green: 70/255, blue: 128/255))
            .cornerRadius(15.0)
    }
}
Run Code Online (Sandbox Code Playgroud)

这些写起来非常简单。您只需将所需的修饰符应用于内容参数即可。

为了使它们更易于使用,您可以编写扩展View

extension View {
    func inputTextFieldStyle() -> some View {
        modifier(InputTextFieldModifier())
    }

    func buttonTextStyle() -> some View {
        modifier(ButtonTextModifier())
    }
}
Run Code Online (Sandbox Code Playgroud)

这使得调用站点看起来像这样:

var body: some View {
    VStack {
        
        ...
        TextField(...)
            .inputTextFieldStyle()
        ...
        Button(action: {print("Button clicked")}){
            Text("LOGIN")
                .buttonTextStyle()
        }.padding()
        
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您希望能够配置修改器,那也很容易。假设您想指定常用文本字段的背景颜色,您可以重写修饰符以将其作为参数:

struct InputTextFieldModifier: ViewModifier {
    let backgroundColor: Color

    func body(content: Content) -> some View {
        content
            .padding()
            .background(backgroundColor)
            .cornerRadius(5.0)
            .padding(.bottom, 20)
    }
}
Run Code Online (Sandbox Code Playgroud)

并更新您的便利函数以将此作为参数:

extension View {
    func inputTextFieldStyle(backgroundColor: Color) -> some View {
        modifier(InputTextFieldModifier(backgroundColor: backgroundColor))
    }
}
Run Code Online (Sandbox Code Playgroud)

在呼叫站点:

TextField("Username", text: $username)
    .inputTextFieldStyle(backgroundColor: Color.gray)
Run Code Online (Sandbox Code Playgroud)

并且自定义修饰符是可重用的。

  • 出色的!我同意您的观点,使用自定义“ViewModifier”是应用多个 SwiftUI 视图修饰符来设置“View”样式的更好选择,而不是使用自定义“View”。 (2认同)