So my goal is to have a more convenient method for adding a placeholder text value on SwiftUI's TextEditor, since there doesn't appear to be one. The approach I'm trying has uncovered something I really don't understand around Binding<> wrapped types. (Maybe this is a red flag that I'm doing something not recommended?)
Anyway, on to my question: are we able to programmatically update the underlying values on Bindings? If I accept some Binding<String> value, can I update it from within my method here? If so, will the updated value be referenced by the @State originator? The below example places my placeholder value in as text where I'm trying to type when you click into it, and does not even attempt it again if I clear it out.
Imported this code from other posts I found some time ago to make it display a placeholder if the body is empty.
import Foundation
import SwiftUI
struct TextEditorViewThing: View {
@State private var noteText = ""
var body: some View {
VStack{
TextEditor(text: $noteText)
.textPlaceholder(placeholder: "PLACEHOLDER", text: $noteText)
.padding()
}
}
}
extension TextEditor {
@ViewBuilder func textPlaceholder(placeholder: String, text: Binding<String>) -> some View {
self.onAppear {
// remove the placeholder text when keyboard appears
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: .main) { (noti) in
withAnimation {
if text.wrappedValue == placeholder {
text.wrappedValue = placeholder
}
}
}
// put back the placeholder text if the user dismisses the keyboard without adding any text
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: .main) { (noti) in
withAnimation {
if text.wrappedValue == "" {
text.wrappedValue = placeholder
}
}
}
}
}
}