49

Let's say that I am making a custom input element that looks like this:

struct CustomInput : View {
    @Binding var text: String
    var name: String

    var body: some View {
        TextField(name, text: $text)
            .modifier(InputModifier())

    }
}

Currently, when I instantiate this view I'm required to pass both text and name names to arguments. I want to be able to make the name argument optional, like in the example below.

 CustomInput("Some name", $text)

Typically I'd use an init method for this. But I'm not sure how to handle property wrappers like @Binding in the init function.

Any ideas on how I can achieve this?

bento
  • 4,846
  • 8
  • 41
  • 59

1 Answers1

78

You can write your initializer like this:

struct CustomInput : View {
    @Binding var text: String
    var name: String

    init(_ name: String, _ text: Binding<String>) {
        self.name = name

        // Beta 3
        // self.$text = text

        // Beta 4
        self._text = text
    }

    var body: some View {
        TextField(name, text: $text)
    }
}
kontiki
  • 37,663
  • 13
  • 111
  • 125
  • Property wrappers changed in beta 4, code updated to reflect that. – kontiki Jul 18 '19 at 05:12
  • 3
    @matt: The $ accesor is now non mutable. When initialising it that way with beta4, the compiler will give you: ***Cannot assign to property: '$text' is immutable***. Note that the dollar sign is still used for passing a binding, the underscore is only necessary when initialising it. – kontiki Jul 18 '19 at 05:26
  • 1
    Yes, I figured it out. You haven’t quite described correctly what they did but I am really glad you alerted me to this change! Thanks very much. Here is a summary of the change: https://forums.swift.org/t/se-0258-property-wrappers-third-review/26399 – matt Jul 18 '19 at 06:28