Last active
January 23, 2025 12:09
-
-
Save jbnunn/dab656b53f6e4ee2f53730f0b8daee64 to your computer and use it in GitHub Desktop.
SwiftUI + PhoneNumberKit implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import SwiftUI | |
| import UIKit | |
| import PhoneNumberKit | |
| struct PhoneNumberTextFieldView: UIViewRepresentable { | |
| @Binding var phoneNumber: String | |
| private let textField = PhoneNumberTextField() | |
| func makeUIView(context: Context) -> PhoneNumberTextField { | |
| textField.withExamplePlaceholder = true | |
| //textField.font = UIFont(name: GlobalConstant.paragraphFont.rawValue, size: 17) | |
| textField.withFlag = true | |
| textField.withPrefix = true | |
| // textField.placeholder = "Enter phone number" | |
| textField.becomeFirstResponder() | |
| return textField | |
| } | |
| func getCurrentText() { | |
| self.phoneNumber = textField.text! | |
| } | |
| func updateUIView(_ view: PhoneNumberTextField, context: Context) { | |
| } | |
| } | |
| struct SignUpSignInView: View { | |
| @State private var phoneNumber = String() | |
| @State private var validationError = false | |
| @State private var errorDesc = Text("") | |
| @State private var phoneField: PhoneNumberTextFieldView? | |
| let phoneNumberKit = PhoneNumberKit() | |
| var body: some View { | |
| ZStack { | |
| VStack(alignment: .leading) { | |
| Text("Sign in with your phone number") | |
| self.phoneField | |
| .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 60) | |
| .keyboardType(.phonePad) | |
| Button(action: { | |
| do { | |
| self.phoneField?.getCurrentText() | |
| print("phone is: \(self.phoneNumber)") | |
| let validatedPhoneNumber = try self.phoneNumberKit.parse(self.phoneNumber) | |
| print("Validated Number: \(validatedPhoneNumber)") | |
| // Integrate with your login/registration system here... | |
| } | |
| catch { | |
| self.validationError = true | |
| self.errorDesc = Text("Please enter a valid phone number") | |
| } | |
| }) { | |
| Text("Sign in") | |
| } | |
| .padding(15) | |
| Spacer() | |
| } | |
| .padding() | |
| .onAppear { | |
| self.phoneField = PhoneNumberTextFieldView(phoneNumber: self.$phoneNumber) | |
| } | |
| .alert(isPresented: self.$validationError) { | |
| Alert(title: Text(""), message: self.errorDesc, dismissButton: .default(Text("OK"))) | |
| } | |
| } | |
| } | |
| } |
Use more canonical and idiomatic Swift code if you are targeting iOS 13.0+
import SwiftUI
import PhoneNumberKit
struct PhoneNumberField: UIViewRepresentable {
@Binding var text: String
func makeUIView(context: Context) -> PhoneNumberTextField {
let textField = PhoneNumberTextField()
textField.withPrefix = true
textField.withFlag = true
textField.withExamplePlaceholder = true
textField.withDefaultPickerUI = true
textField.delegate = context.coordinator
textField.becomeFirstResponder()
return textField
}
func updateUIView(_ uiView: PhoneNumberTextField, context: Context) {
uiView.text = text
guard let phoneNumber = uiView.phoneNumber else {
return
}
if phoneNumber.countryCode == 82, phoneNumber.type == .mobile, String(phoneNumber.nationalNumber).count != 10 {
// Obsolete Korean mobile phone number
// e.g. 011-123-4567
return
}
DispatchQueue.main.async {
uiView.resignFirstResponder()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: PhoneNumberField
init(_ parent: PhoneNumberField) {
self.parent = parent
}
func textFieldDidChangeSelection(_ textField: UITextField) {
if let text = textField.text {
parent.text = text
}
}
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm also wondering if anyone was able to make the country picker work in SwiftUI? The samples posted here work well but the country picker does not seem to be supported.
Update: It works perfectly fine by simply adding this line:
textField.withDefaultPickerUI = true