我当前的代码可以工作,但我想看看是否有更好的方法。
我有一个视图设置,以便一旦用户开始在文本字段中输入数据,就会出现一个新的文本字段。
我想知道这是否可以通过 ForEach 循环来完成,或者是否有更好的方法来编写此代码。
这是模型
import FirebaseFirestore
import MetaCodable
@Codable
struct Trip: Identifiable, Equatable, Hashable {
@DocumentID @Default(UUID().uuidString) var id: String?
@Default("") var bol: String
@Default("") var bol1: String
@Default("") var bol2: String
@Default("") var bol3: String
@Default("") var bol4: String
@Default("") var bol5: String
@Default("") var bol6: String
@Default("") var bol7: String
@Default("") var bol8: String
@Default("") var bol9: String
init(
bol: String = "",
bol1: String = "",
bol2: String = "",
bol3: String = "",
bol4: String = "",
bol5: String = "",
bol6: String = "",
bol7: String = "",
bol8: String = "",
bol9: String = ""
) {
self.bol = bol
self.bol1 = bol1
self.bol2 = bol2
self.bol3 = bol3
self.bol4 = bol4
self.bol5 = bol5
self.bol6 = bol6
self.bol7 = bol7
self.bol8 = bol8
self.bol9 = bol9
}
}
文本字段子视图
struct TextFieldRowView: View {
let title: String
let placeholder: String
let width: CGFloat
@Binding var text: String
var body: some View {
ViewThatFits(in: .horizontal) {
LabeledContent {
TextField(placeholder, text: $text)
.frame(width: width, alignment: .leading)
.textInputAutocapitalization(.words)
.autocorrectionDisabled()
} label: {
Text(title)
.bold()
}
VStack {
Text(title)
.bold()
TextField(placeholder, text: $text)
.frame(width: width, alignment: .leading)
.textInputAutocapitalization(.words)
.autocorrectionDisabled()
}
}
}
}
和景色
import SwiftUI
struct AddEditTripView: View {
@FocusState private var focusField: Field?
@State private var bol = ""
@State private var bol1 = ""
@State private var bol2 = ""
@State private var bol3 = ""
@State private var bol4 = ""
@State private var bol5 = ""
@State private var bol6 = ""
@State private var bol7 = ""
@State private var bol8 = ""
@State private var bol9 = ""
var body: some View {
Form {
// MARK: - Trip Information
Section {
// MARK: - BOL
TextFieldRowView(title: "BOL:", placeholder: "bol", width: UIScreen.main.bounds.width - 230, text: $bol)
.focused($focusField, equals: .bol)
.submitLabel(.next)
if !bol.isEmpty {
TextFieldRowView(title: "BOL:", placeholder: "bol", width: UIScreen.main.bounds.width - 230, text: $bol1)
.focused($focusField, equals: .bol1)
.submitLabel(.next)
}
if !bol1.isEmpty {
TextFieldRowView(title: "BOL:", placeholder: "bol", width: UIScreen.main.bounds.width - 230, text: $bol2)
.focused($focusField, equals: .bol2)
.submitLabel(.next)
}
if !bol2.isEmpty {
TextFieldRowView(title: "BOL:", placeholder: "bol", width: UIScreen.main.bounds.width - 230, text: $bol3)
.focused($focusField, equals: .bol3)
.submitLabel(.next)
}
if !bol3.isEmpty {
TextFieldRowView(title: "BOL:", placeholder: "bol", width: UIScreen.main.bounds.width - 230, text: $bol4)
.focused($focusField, equals: .bol4)
.submitLabel(.next)
}
if !bol4.isEmpty {
TextFieldRowView(title: "BOL:", placeholder: "bol", width: UIScreen.main.bounds.width - 230, text: $bol5)
.focused($focusField, equals: .bol5)
.submitLabel(.next)
}
if !bol5.isEmpty {
TextFieldRowView(title: "BOL:", placeholder: "bol", width: UIScreen.main.bounds.width - 230, text: $bol6)
.focused($focusField, equals: .bol6)
.submitLabel(.next)
}
if !bol6.isEmpty {
TextFieldRowView(title: "BOL:", placeholder: "bol", width: UIScreen.main.bounds.width - 230, text: $bol7)
.focused($focusField, equals: .bol7)
.submitLabel(.next)
}
if !bol7.isEmpty {
TextFieldRowView(title: "BOL:", placeholder: "bol", width: UIScreen.main.bounds.width - 230, text: $bol8)
.focused($focusField, equals: .bol8)
.submitLabel(.next)
}
if !bol8.isEmpty {
TextFieldRowView(title: "BOL:", placeholder: "bol", width: UIScreen.main.bounds.width - 230, text: $bol9)
.focused($focusField, equals: .bol9)
.submitLabel(.next)
}
}
}
}
}
extension AddEditTripView {
private enum Field {
case bol, bol1, bol2, bol3, bol4, bol5, bol6, bol7, bol8, bol9
}
private func focusNextField() {
switch focusField {
case .bol:
focusField = .bol1
case .bol1:
focusField = .bol2
case .bol2:
focusField = .bol3
case .bol3:
focusField = .bol4
case .bol4:
focusField = .bol5
case .bol5:
focusField = .bol6
case .bol6:
focusField = .bol7
case .bol7:
focusField = .bol8
case .bol8:
focusField = .bol9
case .bol9:
focusField = nil
case .none:
break
}
}
}
将所有
bol
存储到一个数组中,并使用 ForEach
迭代该数组。
@FocusState private var focusField: Field?
@State private var bols = Array(repeating: "", count: 10)
var body: some View {
Form {
Section {
ForEach(0..<10) { i in
if i == 0 || !bols[i - 1].isEmpty {
TextFieldRowView(
title: "BOL:",
placeholder: "bol",
width: UIScreen.main.bounds.width - 230,
text: $bols[i]
)
.focused($focusField, equals: Field(rawValue: i))
.submitLabel(.next)
}
}
}
}
}
注意
i == 0
析取。这无条件地显示第一个文本字段,并且仅当前一个字段不为空时才显示所有其他文本字段。
注意
Field(rawValue: i)
。 Field
应将 Int
作为其原始值类型。这使得使用 Field
轻松创建 Int
的值。您还可以轻松编写一个 nextField
方法:
enum Field: Int {
case bol, bol1, bol2, bol3, bol4, bol5, bol6, bol7, bol8, bol9
func nextField() -> Field? {
Field(rawValue: rawValue + 1)
}
}
然后移动到下一个字段就像这样简单,
.onSubmit {
focusField = focusField?.nextField()
}