Objective-C中手机号输入的国家码前缀UI实现方案问询
我来帮你梳理下这个需求的实现思路和具体代码片段,都是iOS开发里很常用的套路~
整体实现思路拆解
这个需求可以拆成三个核心模块来完成:
- 自定义带底部线条+右侧>符号的UITextField
- 实现国家码选择页面(用TableView展示你的国家码数组)
- 完成选择页和原页面的数据回传,填充选中的国家码
一、自定义带线条和箭头的UITextField
系统默认的UITextField没有底部线条,我们可以通过自定义子类来实现样式,同时把右侧的>做成可点击的按钮(比单纯加Label体验更好),并且禁止TextField手动编辑(毕竟是选择填充,不是输入)。
import UIKit class CountryCodeTextField: UITextField { // 右侧箭头按钮 private let arrowButton: UIButton = { let button = UIButton(type: .system) button.setTitle(">", for: .normal) button.setTitleColor(.darkGray, for: .normal) button.addTarget(self, action: #selector(arrowTapped), for: .touchUpInside) return button }() // 底部线条 private let bottomLine: UIView = { let line = UIView() line.backgroundColor = .lightGray return line }() // 点击箭头的回调,用来通知控制器跳转 var onArrowTapped: (() -> Void)? override init(frame: CGRect) { super.init(frame: frame) setupUI() } required init?(coder: NSCoder) { super.init(coder: coder) setupUI() } private func setupUI() { // 禁止手动编辑,只允许点击箭头选择 isEditable = false isUserInteractionEnabled = true // 添加底部线条约束 addSubview(bottomLine) bottomLine.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ bottomLine.leadingAnchor.constraint(equalTo: leadingAnchor), bottomLine.trailingAnchor.constraint(equalTo: trailingAnchor), bottomLine.bottomAnchor.constraint(equalTo: bottomAnchor), bottomLine.heightAnchor.constraint(equalToConstant: 1) ]) // 添加右侧箭头按钮约束 addSubview(arrowButton) arrowButton.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ arrowButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8), arrowButton.centerYAnchor.constraint(equalTo: centerYAnchor), arrowButton.widthAnchor.constraint(equalToConstant: 20), arrowButton.heightAnchor.constraint(equalTo: heightAnchor) ]) // 设置左内边距,避免文字贴边 leftView = UIView(frame: CGRect(x: 0, y: 0, width: 8, height: 0)) leftViewMode = .always } @objc private func arrowTapped() { onArrowTapped?() } }
二、实现国家码选择页面
用UITableView来展示你现有的国家码数组,建议先把数组转成结构化的模型(方便管理国家名称和代码),然后通过回调把选中的代码回传给原页面。
第一步:定义国家码模型
struct CountryCodeModel { let countryName: String let code: String // 比如 "+86"、"+1" }
第二步:实现选择页ViewController
import UIKit class CountryCodePickerVC: UIViewController { private let tableView = UITableView() // 接收外部传入的国家码数组 var countryCodes: [CountryCodeModel] = [] // 选择完成的回调,回传选中的国家码 var onCodeSelected: ((String) -> Void)? override func viewDidLoad() { super.viewDidLoad() setupTableView() title = "选择国家/地区码" navigationItem.leftBarButtonItem = UIBarButtonItem(title: "取消", style: .plain, target: self, action: #selector(dismissVC)) } private func setupTableView() { view.addSubview(tableView) tableView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) ]) tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") tableView.dataSource = self tableView.delegate = self } @objc private func dismissVC() { dismiss(animated: true) } } extension CountryCodePickerVC: UITableViewDataSource, UITableViewDelegate { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return countryCodes.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) let model = countryCodes[indexPath.row] cell.textLabel?.text = "\(model.countryName) \(model.code)" return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) let selectedCode = countryCodes[indexPath.row].code onCodeSelected?(selectedCode) dismiss(animated: true) } }
三、原页面整合逻辑
在你的主ViewController里,初始化自定义TextField,绑定跳转事件,接收选择页回传的国家码并填充。
import UIKit class MainVC: UIViewController { private let countryCodeTextField = CountryCodeTextField() // 假设你的国家码数组是这个,替换成你现有的NSMutableArray即可 private var countryCodesArray: [CountryCodeModel] = [ CountryCodeModel(countryName: "中国", code: "+86"), CountryCodeModel(countryName: "美国", code: "+1"), CountryCodeModel(countryName: "日本", code: "+81") ] override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white setupTextField() } private func setupTextField() { view.addSubview(countryCodeTextField) countryCodeTextField.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ countryCodeTextField.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 50), countryCodeTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), countryCodeTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20), countryCodeTextField.heightAnchor.constraint(equalToConstant: 44) ]) countryCodeTextField.placeholder = "请选择国家/地区码" // 绑定箭头点击事件,跳转选择页 countryCodeTextField.onArrowTapped = { [weak self] in guard let self = self else { return } let pickerVC = CountryCodePickerVC() pickerVC.countryCodes = self.countryCodesArray // 接收选中的国家码,填充到TextField pickerVC.onCodeSelected = { selectedCode in self.countryCodeTextField.text = selectedCode } self.present(pickerVC, animated: true) } } }
额外优化建议
- 如果你的国家码数组是Objective-C的
NSMutableArray,可以遍历转换成Swift数组或者直接在OC中实现相同逻辑(思路完全一致)。 - 可以给选择页添加搜索栏,方便用户快速定位国家,提升体验。
- 可以自定义TableViewCell的样式,让国家码展示更清晰。
内容的提问来源于stack exchange,提问作者Hanz Cheah
相关产品推荐
相关产品推荐

