SwiftUI TextEditor doesn't work in a SwiftUI Form

Has anyone been able to get the new TextEditor view to work in SwiftUI form? I've tried different things and it seems like the row isn't aware of the size of the TextEditor as you type and it grows.

I'd be more than happy to file a radar with example code if needed.
Post not yet marked as solved Up vote post of mmendoza27 Down vote post of mmendoza27
1.3k views

Answers

I have the same issue. I just put the TextEditor outside of the Form. Hope they will fix it.
Same issue, when embedded within a form the row looks aweful.

I would expect the formatting to be the same when placed within a Form as essentially just a multiline TextField.
For now, I've just manually overriden the underlying UIKit element styling to allow for custom background support on the element, next to figure out how to pad the entry and set a placeholder.

Original fix can be found, as everything, on StackOverflow.

Code Block swift
struct MyView: View {
@State private var name: String = ""
@State private var description: String = ""
init() {
/* Override TextEditor background to allow for setting a custom background in SwiftUI */
UITextView.appearance().backgroundColor = .clear
}
var body: some View {
NavigationView {
Form {
Section(header: Text("Details")) {
TextField("Name", text: self.$name)
TextEditor(text: self.$description)
.background(Color(.secondarySystemGroupedBackground))
/* Set the background to that of the grouped background colour */
}
}
.navigationBarTitle("New Thing")
}
}
}


I'm trying to emulate the multiline edit field that is present in the Reminders app, where you set a title and description.

PS. Also Apple, fix your syntax highlighting in code blocks to support double forward slash...
Okay, so after some more research, I've gotten it as close to a natural SwiftUI element design as I can. There is still some padding that I cannot control that throws off the cursor and placeholder alignment that I'm not sure can be 'fixed'.

Again, making reference to tips found on how to accomplish this on StackOverflow.

Code Block swift
struct MyView: View {
@State private var name: String = ""
@State private var description: String = ""
init() {
/* Override TextEditor background to allow for setting a custom background in SwiftUI */
UITextView.appearance().backgroundColor = .clear
}
var body: some View {
NavigationView {
Form {
Section(header: Text("Details")) {
TextField("Name", text: self.$name)
ZStack(alignment: .leading) {
if self.description.isEmpty {
VStack {
Text("Description")
.padding(.top, 8)
.padding(.leading, 1)
Spacer()
}
}
TextEditor(text: self.$description)
/* Set the background to that of the grouped background colour */
.background(Color(.secondarySystemGroupedBackground))
/* Allow the text overlay to be seen and emulate the necessary colour */
.opacity(self.description.isEmpty ? 0.7 : 1)
}
.frame(height: 125)
}
}
.navigationBarTitle("New Goal")
}
}
}


It's not a great answer, but here's what I've come up with, and it actually works quite well:

Code Block swift
struct EditableTextRow: View {
@State var text: String = ""
var body: some View {
ZStack(alignment: .leading) {
Text(text)
.padding([.leading, .trailing], 5)
.padding([.top, .bottom], 8)
.foregroundColor(Color.clear)
TextEditor(text: self.$text)
}
}
}


It even works correctly with dynamic type, though there may be other accessibility impacts I haven't run into yet.
Hey,

In case it can help someone, here is a version to have within a Form. Works well with iOS 14 on iPhone.
I have a version similar to Othyn.

I added a negative (horizontal) padding to resolve the layout issue.

Code Block swift
      ZStack {
          if self.itemDescription.isEmpty == true {
            Text("placeholder")
              .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
              .foregroundColor(Color.tertiaryLabel)
          }
          TextEditor(text: self.$itemDescription)
            .frame(maxHeight: .infinity)
            .padding(.horizontal, -5)
      }
      .font(.body)


Cheers