【发布时间】:2022-07-31 06:15:19
【问题描述】:
SwiftUI 有两种不同形式的文本字段,一种是隐藏输入的 SecureField 和不隐藏输入的 TextField。除了创建两个单独的视图之外,有没有一种方法可以创建一个单独的视图,该视图接受一个参数来创建两种类型,同时尽可能少地重复代码?
【问题讨论】:
SwiftUI 有两种不同形式的文本字段,一种是隐藏输入的 SecureField 和不隐藏输入的 TextField。除了创建两个单独的视图之外,有没有一种方法可以创建一个单独的视图,该视图接受一个参数来创建两种类型,同时尽可能少地重复代码?
【问题讨论】:
您只需使用 SecureTextField 和 TextField 所需的所有代码创建一个 View,然后您只需在需要时调用 HybridTextField。
import SwiftUI
struct HybridTextFieldUsageView: View {
@State var password: String = "password"
@State var viewSecure: Bool = true
var body: some View {
//Use this anywhere in your code
HybridTextField(text: $password, titleKey: "password")
}
}
///Contains all the code for the Secure and regular TextFields
struct HybridTextField: View {
@Binding var text: String
@State var isSecure: Bool = true
var titleKey: String
var body: some View {
HStack{
Group{
if isSecure{
SecureField(titleKey, text: $text)
}else{
TextField(titleKey, text: $text)
}
}.textFieldStyle(.roundedBorder)
.animation(.easeInOut(duration: 0.2), value: isSecure)
//Add any common modifiers here so they dont have to be repeated for each Field
Button(action: {
isSecure.toggle()
}, label: {
Image(systemName: !isSecure ? "eye.slash" : "eye" )
})
}//Add any modifiers shared by the Button and the Fields here
}
}
struct HybridTextField_Previews: PreviewProvider {
static var previews: some View {
HybridTextFieldUsageView()
}
}
【讨论】:
如何在此处添加对密码验证功能的调用?所以如果我想检查密码是否足够强大,那么我有以下功能:
func validatePassword(passwordString:String?) -> Bool {
guard passwordString != nil else { return false }
let passwordTest = NSPredicate(format: "SELF MATCHES %@", "(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{8,}")
return passwordTest.evaluate(with: passwordString)
}
【讨论】:
在您的视图主体中,您可以根据需要使用三元组来创建正确的文本字段,而无需使用巨大的 if/else 块:
(self.isSecure ? AnyView(SecureField(placeholder, text: $value)) : AnyView(TextField(placeholder, text: $value)))
这将返回一个您可以在其上使用运算符的视图,如果您正在创建自定义文本输入,这将非常有用。例如,如果我们必须为每种类型的文本字段执行两次,那么下面的内容将会很痛苦。在实际的视图主体中使用三元组可以避免出现两个巨大的 if/else 块。
VStack {
ZStack(alignment: .leading) {
Text(placeholder)
.foregroundColor(Color(.placeholderText))
.offset(y: $value.wrappedValue.isEmpty ? 0 : -25)
.scaleEffect($value.wrappedValue.isEmpty ? 1 : 0.8, anchor: .leading)
(self.isSecure ? AnyView(SecureField(placeholder, text: $value)) : AnyView(TextField(placeholder, text: $value)))
.onChange(of: self.value) { newValue in
if self.onChange(newValue) != true {
self.value = previousValue
}
DispatchQueue.main.async {
self.previousValue = newValue
}
}
}
.padding(.top, 15)
.animation(.easeInOut(duration: 0.2))
Divider()
.frame(height: 1)
.padding(.horizontal, 30)
.background(Color.black)
}
【讨论】:
AnyView 被 Apple developer.apple.com/wwdc21/10022 劝阻
Views 的三元运算也因速度慢(构建时间长)和导致崩溃 stackoverflow.com/search?tab=newest&q=swiftui%20ternary 而臭名昭著