将 @State 值委托给 child 组件

Delegate @State value to a child component

这里有一个 Swift 新人。试图理解 SwiftUI。 我正在尝试创建一个包装文本和文本字段的 "Field" 组件。这个想法是用更少的代码并有一个可以显示字段标题及其对应值的控件。

我不知道如何在我的控件上分配模型的值。

这是我的模型:

import Foundation

class EmployeeModel {

    var FullName: String = "John Doe"
    var JobStartDate: String = ""
    var BornDate: String = ""
    var DepartmentId: Int = 0
    var DepartmentName: String = ""
    var isBossDepartment: Bool = false
    var JobPositionId: Int = 0
    var JobPositionName: String = ""
    var PersonalDocNumber: String = ""
    var Password: String = ""

    init() {
    }

}

在视图的某些部分...

struct EmployeeView : View {
    @State private var Employee = EmployeeModel()

    var body : some View {
        Field("Full Name", $Employee.FullName)
    }
}

这是我要实现的自定义组件。

struct Field : View {
    private var caption: String = ""
    @State private var controlValue: String = ""

    init(caption: String, value: String) {
        self.caption = caption
        controlValue = value
    }

    var body : some View {
        VStack {
            Text(self.caption)
            TextField($controlValue)
                .textFieldStyle(.roundedBorder)
        }
    }
}

目前我收到了

的消息

'Binding' 在我的 EmployeeView

字段实现中不能转换为 'String'

在进入您的问题的细节之前,请注意,按照惯例,类型(类、结构、枚举等)应该以大写字母开头,而对象和值应该以小写(或下划线)。如果不遵循该约定,就会让其他人难以阅读代码,正如每个人所期望的那样。

现在,您的代码有几处改进:

  1. controlValue 必须声明为 @Binding.
  2. @Binding 属性不应有初始值,因为它们应该由调用者传递。
  3. 如果您将属性声明为非私有,则不需要初始化程序。这没什么问题,但如果您确实使用了初始化程序,则需要执行多项更改(请参阅下面的代码)。
  4. 您的 TextField 在 beta 5 中使用了已弃用且已停用的初始化程序。
struct EmployeeModel {

    var fullName: String = "John Doe"
    var jobStartDate: String = ""
    var bornDate: String = ""
    var departmentId: Int = 0
    var departmentName: String = ""
    var isBossDepartment: Bool = false
    var jobPositionId: Int = 0
    var jobPositionName: String = ""
    var personalDocNumber: String = ""
    var password: String = ""

    init() {
    }

}

struct EmployeeView : View {
    @State private var employee = EmployeeModel()

    var body : some View {
        Field(caption: "Full Name", value: $employee.fullName)
    }
}

struct Field : View {
    private var caption: String = ""
    @Binding private var controlValue: String

    init(caption: String, value: Binding<String>) {
        self.caption = caption
        self._controlValue = value
    }

    var body : some View {
        VStack {
            Text(self.caption)
            TextField("", text: $controlValue)
                .textFieldStyle(.roundedBorder)
        }
    }
}