feat(gift): 연락처 입력 규칙을 추가한다
This commit is contained in:
@@ -41,6 +41,10 @@ enum SodaTypography {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func localizedFontName(locale: Locale = .autoupdatingCurrent) -> String? {
|
||||||
|
fontName(for: .localized, weight: weight, locale: locale)
|
||||||
|
}
|
||||||
|
|
||||||
var weight: SwiftUI.Font.Weight {
|
var weight: SwiftUI.Font.Weight {
|
||||||
switch self {
|
switch self {
|
||||||
case .heading1, .heading2, .heading3, .heading4, .body1, .body4, .caption1:
|
case .heading1, .heading2, .heading3, .heading4, .body1, .body4, .caption1:
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
enum GiftContactInputRule {
|
||||||
|
case name
|
||||||
|
case phoneNumber
|
||||||
|
|
||||||
|
func acceptsEditing(_ text: String) -> Bool {
|
||||||
|
switch self {
|
||||||
|
case .name:
|
||||||
|
return text.count <= 12 && text.unicodeScalars.allSatisfy { scalar in
|
||||||
|
switch scalar.value {
|
||||||
|
case 0x41...0x5A, 0x61...0x7A,
|
||||||
|
0x1100...0x11FF, 0x3130...0x318F,
|
||||||
|
0xA960...0xA97F, 0xAC00...0xD7A3, 0xD7B0...0xD7FF:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .phoneNumber:
|
||||||
|
return text.count <= 11 && text.unicodeScalars.allSatisfy {
|
||||||
|
(0x30...0x39).contains($0.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func acceptsSubmission(_ text: String) -> Bool {
|
||||||
|
switch self {
|
||||||
|
case .name:
|
||||||
|
return !text.isEmpty && acceptsEditing(text)
|
||||||
|
case .phoneNumber:
|
||||||
|
return text.count == 11 && text.hasPrefix("010") && acceptsEditing(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user