import SwiftUI import UIKit struct GiftContactTextField: UIViewRepresentable { @Binding var text: String let rule: GiftContactInputRule func makeCoordinator() -> Coordinator { Coordinator(parent: self) } func makeUIView(context: Context) -> UITextField { let textField = UITextField(frame: .zero) textField.delegate = context.coordinator textField.text = text textField.backgroundColor = .clear textField.textColor = .white textField.font = SodaTypography.body3.localizedFontName() .flatMap { UIFont(name: $0, size: SodaTypography.body3.size) } ?? UIFont.systemFont(ofSize: SodaTypography.body3.size, weight: .regular) textField.autocorrectionType = .no textField.autocapitalizationType = .none let placeholder: String switch rule { case .name: placeholder = "이름을 입력해 주세요" textField.textContentType = .name case .phoneNumber: placeholder = "휴대폰 번호를 입력해 주세요" textField.keyboardType = .numberPad textField.textContentType = .telephoneNumber } textField.attributedPlaceholder = NSAttributedString( string: placeholder, attributes: [.foregroundColor: UIColor(Color.gray600)] ) textField.setContentHuggingPriority(.defaultLow, for: .horizontal) textField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) textField.addTarget(context.coordinator, action: #selector(Coordinator.textDidChange(_:)), for: .editingChanged) return textField } func updateUIView(_ uiView: UITextField, context: Context) { context.coordinator.parent = self guard uiView.markedTextRange == nil, text != context.coordinator.lastAcceptedText, rule.acceptsEditing(text) else { return } context.coordinator.lastAcceptedText = text if uiView.text != text { uiView.text = text } } final class Coordinator: NSObject, UITextFieldDelegate { var parent: GiftContactTextField var lastAcceptedText: String init(parent: GiftContactTextField) { self.parent = parent lastAcceptedText = parent.rule.acceptsEditing(parent.text) ? parent.text : "" } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString replacement: String) -> Bool { guard textField.markedTextRange == nil else { return true } let current = textField.text ?? "" let prospective = (current as NSString).replacingCharacters(in: range, with: replacement) return parent.rule.acceptsEditing(prospective) } @objc func textDidChange(_ textField: UITextField) { guard textField.markedTextRange == nil else { return } let committed = textField.text ?? "" guard parent.rule.acceptsEditing(committed) else { textField.text = lastAcceptedText return } lastAcceptedText = committed if parent.text != committed { parent.text = committed } } func textFieldDidChangeSelection(_ textField: UITextField) { textDidChange(textField) } func textFieldDidEndEditing(_ textField: UITextField) { textDidChange(textField) } } }