iOS中是否有Android的PhoneNumberUtils.formatNumber系列等效函数?
当然有啦!iOS 平台上有几种靠谱的方案可以实现和 Android PhoneNumberUtils.formatNumber、PhoneNumberUtils.formatNumberToE164 几乎完全等效的功能,刚好匹配你把号码存为 Int64、展示时再格式化的需求。
一、官方 Contacts 框架(iOS 10+,无需第三方库)
苹果自带的 Contacts 框架里的 CNPhoneNumberFormatter 就能满足基础需求,不用额外引入依赖。
1. 格式化号码用于用户展示(对应 PhoneNumberUtils.formatNumber)
从数据库取出 Int64 类型的号码后,先转成字符串,再用这个工具类根据系统区域设置自动格式化:
import Contacts func formatPhoneNumberForDisplay(_ number: Int64) -> String? { let numberString = String(number) guard let phoneNumber = CNPhoneNumber(stringValue: numberString) else { return nil } let formatter = CNPhoneNumberFormatter() // 可以根据需求设置样式:.default(本地格式)、.international(国际格式)等 formatter.style = .default return formatter.string(from: phoneNumber) }
比如国内号码会被格式化为 138 **** 8888 或 138-xxxx-8888(取决于系统设置),美国号码则会变成 (123) 456-7890,非常贴合用户的使用习惯。
2. 格式化为 E.164 标准格式(对应 PhoneNumberUtils.formatNumberToE164)
E.164 格式需要明确号码的国家代码(比如中国是 CN,美国是 US),因为你存在数据库的是纯数字,没有国家码标识,所以建议存号码时同时记录国家码,或者默认使用用户所在区域的国家码:
import Contacts func formatPhoneNumberToE164(_ number: Int64, countryCode: String) -> String? { let numberString = String(number) guard let phoneNumber = CNPhoneNumber(stringValue: numberString, countryCode: countryCode) else { return nil } let formatter = CNPhoneNumberFormatter() formatter.style = .e164 return formatter.string(from: phoneNumber) }
调用后会得到类似 +86138xxxx8888 的标准格式,去掉前面的 + 号就能转成 Int64 存入数据库了。
二、Google libphonenumber-iOS 库(跨平台统一行为首选)
如果你是跨 Android/iOS 开发,想要两端格式化逻辑完全一致,那 Google 官方的 libphonenumber-iOS 绝对是最佳选择——它和 Android 端的 PhoneNumberUtils 同源,底层逻辑完全相同,能处理各种复杂的国际号码场景。
1. 引入库
可以通过 CocoaPods 或 Swift Package Manager 引入:
# Podfile 中添加 pod 'libphonenumber-iOS'
2. 格式化展示号码
import libphonenumber func formatPhoneNumberForDisplay(_ number: Int64) -> String? { let numberString = String(number) let phoneNumberUtil = NBPhoneNumberUtil.sharedInstance() do { // 传入默认区域(比如"CN"),如果号码带国家码也能自动识别 let phoneNumber = try phoneNumberUtil.parse(numberString, defaultRegion: "CN") // .NATIONAL 是本地格式,.INTERNATIONAL 是国际格式 return try phoneNumberUtil.format(phoneNumber, numberFormat: .NATIONAL) } catch { print("号码解析失败: \(error)") return nil } }
3. 转换为 E.164 格式
import libphonenumber func formatPhoneNumberToE164(_ number: Int64, countryCode: String) -> String? { let numberString = String(number) let phoneNumberUtil = NBPhoneNumberUtil.sharedInstance() do { let phoneNumber = try phoneNumberUtil.parse(numberString, defaultRegion: countryCode) return try phoneNumberUtil.format(phoneNumber, numberFormat: .E164) } catch { print("号码解析失败: \(error)") return nil } }
适配你的存储需求
针对你把号码存为 Int64 的场景,建议流程:
- 存储时:先把用户输入的号码转成 E.164 格式,去掉
+号后转成 Int64 存入数据库(比如+86138xxxx8888→86138xxxx8888) - 展示时:从数据库取出 Int64 转成字符串,再用上面的格式化方法转成用户易读的样式
注意:如果是本地号码(不带国家码),一定要记得同步存储国家码,否则后续格式化时可能会识别错误。
内容的提问来源于stack exchange,提问作者zeus

