diff --git a/README.md b/README.md index bdfe3dc..e4dc0f6 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,29 @@ CountryCodePicker.commonCountryCodes = ["US", "GB", "FR"] textField.withDefaultPickerUIOptions.backgroundColor = .systemBackground ``` +### SwiftUI + +Use `PhoneNumberTextFieldRepresentable` to bind a text field to SwiftUI state. Configure the +underlying `PhoneNumberTextField` in the trailing closure: + +```swift +import SwiftUI +import PhoneNumberKitUI + +struct ContentView: View { + @State private var phoneNumber = "" + + var body: some View { + PhoneNumberTextFieldRepresentable(text: $phoneNumber) { textField in + textField.withFlag = true + textField.withPrefix = true + textField.withExamplePlaceholder = true + textField.withDefaultPickerUI = true + } + } +} +``` + Override the default region by subclassing: ```swift diff --git a/Sources/PhoneNumberKitUI/PhoneNumberTextFieldRepresentable.swift b/Sources/PhoneNumberKitUI/PhoneNumberTextFieldRepresentable.swift new file mode 100644 index 0000000..c9321da --- /dev/null +++ b/Sources/PhoneNumberKitUI/PhoneNumberTextFieldRepresentable.swift @@ -0,0 +1,55 @@ +import SwiftUI + +/// A SwiftUI wrapper around ``PhoneNumberTextField``. +public struct PhoneNumberTextFieldRepresentable: UIViewRepresentable { + @Binding private var text: String + private let configure: (PhoneNumberTextField) -> Void + + /// Creates a phone number text field bound to a string. + /// + /// - Parameters: + /// - text: The text displayed and edited by the text field. + /// - configure: A closure for configuring the underlying UIKit text field. + public init( + text: Binding, + configure: @escaping (PhoneNumberTextField) -> Void = { _ in } + ) { + _text = text + self.configure = configure + } + + public func makeUIView(context: Context) -> PhoneNumberTextField { + let textField = PhoneNumberTextField() + configure(textField) + textField.addTarget( + context.coordinator, + action: #selector(Coordinator.textDidChange(_:)), + for: .editingChanged + ) + return textField + } + + public func updateUIView(_ textField: PhoneNumberTextField, context: Context) { + context.coordinator.parent = self + + if textField.text != text { + textField.text = text + } + } + + public func makeCoordinator() -> Coordinator { + Coordinator(parent: self) + } + + public final class Coordinator: NSObject { + fileprivate var parent: PhoneNumberTextFieldRepresentable + + fileprivate init(parent: PhoneNumberTextFieldRepresentable) { + self.parent = parent + } + + @objc fileprivate func textDidChange(_ textField: PhoneNumberTextField) { + parent.text = textField.text ?? "" + } + } +}