Skip to content

Instantly share code, notes, and snippets.

@iampatbrown
Created April 15, 2022 09:59
import SwiftUI
extension TextField {
func fixed() -> some View {
hidden().overlay(FixedTextField(rootView: self))
}
}
struct FixedTextField<Label: View>: UIViewControllerRepresentable {
let rootView: TextField<Label>
func makeUIViewController(context: Context) -> Controller { .init(rootView: rootView) }
func updateUIViewController(_ uiViewController: Controller, context: Context) {}
class Controller: UIHostingController<TextField<Label>> {
var text: String {
withUnsafeBytes(of: rootView) { $0.load(as: Binding<String>.self).wrappedValue }
}
var textField: UITextField? { view.subviews.first?.subviews.first as? UITextField }
override func viewWillLayoutSubviews() {
if let textField = textField, textField.text != text { textField.text = text }
super.viewWillLayoutSubviews()
}
}
}
struct FixedTextFieldStyle<Base: TextFieldStyle>: TextFieldStyle {
let base: Base
func _body(configuration: TextField<_Label>) -> some View {
configuration.fixed().textFieldStyle(base)
}
}
extension TextFieldStyle where Self == FixedTextFieldStyle<DefaultTextFieldStyle> {
static var fixed: Self { .init(base: .automatic) }
}
extension TextFieldStyle {
static func fixed<Base: TextFieldStyle>(_ base: Base) -> FixedTextFieldStyle<Base>
where Self == FixedTextFieldStyle<Base> {
.init(base: base)
}
}
struct ContentView: View {
@State var text = ""
var body: some View {
HStack {
TextField("Type here", text: Binding { text } set: { text = String($0.prefix(5)) })
Text(text)
}
.padding()
.textFieldStyle(.fixed(.roundedBorder))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment