MyTextField
. 用户界面可能是:
代码如下:
struct MyTextField: View {
@Binding var text: String
var label: String
var body: some View {
VStack {
HStack {
Text(label)
Spacer()
}
TextField("", text: $text)
Divider()
}
.padding()
}
}
现在,假设我们希望有另一个具有相同UI的textfield,但要在安全上下文中使用。此文本字段被调用
MySecureTextField
SecureField
而不是
TextField
,但显然我不想这样创建一个全新的视图:
struct MySecureTextField: View {
@Binding var text: String
var label: String
var body: some View {
VStack {
HStack {
Text(label)
Spacer()
}
SecureField("", text: $text)
Divider()
}
.padding()
}
}
我怎么能设计这样的情况?我尝试了几种方法,但都不正确:
要使用以实际文本字段为参数的容器视图排序,请执行以下操作:
struct TextFieldContainer<ActualTextField>: View where ActualTextField: View {
private let actualTextField: () -> ActualTextField
var label: String
init(label: String, @ViewBuilder actualTextField: @escaping () -> ActualTextField) {
self.label = label
self.actualTextField = actualTextField
}
var body: some View {
VStack {
HStack {
Text(label)
Spacer()
}
actualTextField()
Divider()
}
.padding()
}
}
我可以用
TextFieldContainer
这种方式:
struct ContentView: View {
@State private var text = ""
var body: some View {
TextFieldContainer(label: "Label") {
SecureField("", text: self.$text)
}
}
}
我的文本域
或
MySecureTextField
). 这样我甚至可以在容器中注入任何类型的视图,而不仅仅是文本字段。
2秒尝试
要有一个私有容器和两个内部使用该容器的公共视图,请执行以下操作:
private struct TextFieldContainer<ActualTextField>: View where ActualTextField: View {
}
struct MyTextField: View {
@Binding var text: String
let label: String
var body: some View {
TextFieldContainer(label: label) {
TextField("", text: self.$text)
}
}
}
struct MySecureTextField: View {
@Binding var text: String
let label: String
var body: some View {
TextFieldContainer(label: label) {
SecureField("", text: self.$text)
}
}
}
struct ContentView: View {
@State private var text = ""
@State private var text2 = ""
var body: some View {
VStack {
MyTextField(text: $text, label: "Label")
MySecureTextField(text: $text2, label: "Secure textfield")
}
}
}
我并不真的不喜欢这个解决方案,但是在属性上有一些代码重复。如果有很多属性,就会有很多代码重复。另外,如果我在
文本字段容器
我应该更改所有视图,因此,可能要更改很多结构(
我的文本域
,
MySecureTextField
,
MyEmailTextField
MyBlaBlaTextField
,等等)。
3-我最后一次尝试
使用与中相同的方法
第二次尝试
AnyView
这种方式:
struct MySecureTextField: View {
private let content: AnyView
init(text: Binding<String>, label: String) {
content = AnyView(TextFieldContainer(label: label) {
SecureField("", text: text)
})
}
var body: some View {
content
}
}
struct MyTextField: View {
private let content: AnyView
init(text: Binding<String>, label: String) {
content = AnyView(TextFieldContainer(label: label) {
TextField("", text: text)
})
}
var body: some View {
content
}
}