iOS开发:如何获取实体SIM卡数据而非eSIM,或读取双SIM信息检测运营商
解决iOS上优先读取实体SIM卡或检测特定运营商SIM的问题
首先,你的问题核心在于CTTelephonyNetworkInfo的serviceSubscriberCellularProviders是一个无序字典,直接取first或values.first并不能保证拿到实体SIM的数据——iOS会根据当前主卡优先级或激活顺序返回条目,这就是为什么只有实体SIM设为主卡时才能得到预期结果。
针对你的核心需求:检测用户是否使用Free Mobile(MCC 208 / MNC 15)SIM卡
最可靠的方法是遍历所有可用的蜂窝服务条目,直接匹配目标MCC和MNC,不管该SIM是实体还是eSIM。这样既绕开了实体/ eSIM的区分问题,又能精准达成你的检测目标。
修改后的代码如下:
import CoreTelephony func checkForFreeMobileSIM() { let telephonyInfo = CTTelephonyNetworkInfo() // 获取所有蜂窝服务的运营商信息 guard let allCarriers = telephonyInfo.serviceSubscriberCellularProviders else { print("无法获取蜂窝服务信息") return } var targetCarrier: CTCarrier? var targetRadioTech: String? // 遍历所有服务,匹配Free Mobile的MCC和MNC for (serviceId, carrier) in allCarriers { guard let mcc = carrier.mobileCountryCode, let mnc = carrier.mobileNetworkCode else { continue } if mcc == "208" && mnc == "15" { targetCarrier = carrier // 获取对应的无线接入技术并格式化 if let rawTech = telephonyInfo.serviceCurrentRadioAccessTechnology?[serviceId] { targetRadioTech = rawTech.replacingOccurrences(of: "CTRadioAccessTechnology", with: "", options: .literal) } break // 找到第一个匹配的SIM即可,如需检测所有匹配项可移除break } } // 输出结果 if let carrier = targetCarrier { print("检测到Free Mobile SIM卡:") print("- 运营商名称:\(carrier.carrierName ?? "未知")") print("- MCC:\(carrier.mobileCountryCode ?? "未知")") print("- MNC:\(carrier.mobileNetworkCode ?? "未知")") print("- ISO国家码:\(carrier.isoCountryCode?.uppercased() ?? "未知")") print("- 当前无线接入技术:\(targetRadioTech ?? "未知")") } else { print("未检测到Free Mobile SIM卡") } }
如果确实需要优先读取实体SIM卡数据
iOS没有公开的API直接区分实体SIM和eSIM,但可以通过CTCellularPlanManager获取已激活的eSIM计划的服务ID,然后从蜂窝服务列表中排除这些ID,剩下的就是实体SIM的信息:
import CoreTelephony // 获取所有eSIM的服务标识符 private func getESIMServiceIdentifiers() -> [String] { let planManager = CTCellularPlanManager() guard let activePlans = planManager.plans else { return [] } return activePlans.compactMap { $0.serviceIdentifier } } func getPhysicalSIMInfo() { let telephonyInfo = CTTelephonyNetworkInfo() guard let allCarriers = telephonyInfo.serviceSubscriberCellularProviders else { print("无法获取蜂窝服务信息") return } let eSIMServiceIds = getESIMServiceIdentifiers() // 筛选出实体SIM的服务条目 let physicalSIMCarriers = allCarriers.filter { !eSIMServiceIds.contains($0.key) } if let physicalCarrier = physicalSIMCarriers.values.first { print("实体SIM卡信息:") print("- 运营商名称:\(physicalCarrier.carrierName ?? "未知")") print("- MCC:\(physicalCarrier.mobileCountryCode ?? "未知")") print("- MNC:\(physicalCarrier.mobileNetworkCode ?? "未知")") print("- ISO国家码:\(physicalCarrier.isoCountryCode?.uppercased() ?? "未知")") // 获取对应的无线接入技术 if let serviceId = physicalSIMCarriers.keys.first, let rawTech = telephonyInfo.serviceCurrentRadioAccessTechnology?[serviceId] { let formattedTech = rawTech.replacingOccurrences(of: "CTRadioAccessTechnology", with: "", options: .literal) print("- 当前无线接入技术:\(formattedTech)") } } else { print("未检测到实体SIM卡") } }
注意事项
- 确保在
Info.plist中添加NSCellularDataUsageDescription,描述应用需要访问蜂窝数据信息的原因,否则应用会被拒绝访问这些API。 CTCellularPlanManager的部分功能在iOS 12+可用,需要注意版本兼容性。
内容的提问来源于stack exchange,提问作者PlugN
相关产品推荐
相关产品推荐

