如何限制iPhone应用仅在插入SIM卡时运行
iOS:移除SIM卡时弹出提示并限制应用使用
需求
当iPhone移除SIM卡时,弹出提示要求用户插入SIM卡,且在插入SIM卡前应用无法正常使用。
已尝试的无效方案
方案1:通过短信发送能力判断SIM卡状态
试图用canOpenURL("sms:")检测是否能发短信,以此推断SIM卡是否存在,但完全没用。
代码示例:let isCapableToSMS: Bool if UIApplication.shared.canOpenURL(NSURL(string: "sms:")! as URL) { isCapableToSMS = true } else { isCapableToSMS = false } if (!isCapableToSMS || !isCapableToCall) { print ("#######No SIM\n") } else { print ("##### SIM\n") }问题出在:
canOpenURL("sms:")只看系统支不支持短信功能,和有没有SIM卡没关系——就算没插SIM,系统照样能打开短信界面,所以这个判断根本不准。方案2:监听废弃的CTRadioAccessTechnologyDidChange通知
想靠监听CTRadioAccessTechnologyDidChange通知来感知SIM卡变化,但这个通知已经被苹果废弃了,现在用不了。方案3:通过拨打电话能力判断SIM卡状态
和方案1思路一样,用canOpenURL("tel://")检测通话能力,结果同样无效。
代码示例:let isCapableToCall: Bool if UIApplication.shared.canOpenURL(NSURL(string: "tel://")! as URL) { isCapableToCall = true } else { isCapableToCall = false }问题和方案1一致:
canOpenURL("tel://")只检测系统是否支持通话,没SIM卡也能打开拨号界面,无法准确判断SIM卡是否存在。
可行解决方案
用CoreTelephony框架的CTTelephonyNetworkInfo来精准检测SIM卡状态,步骤如下:
- 先导入CoreTelephony框架:
import CoreTelephony
- 初始化
CTTelephonyNetworkInfo,同时监听SIM卡状态变化的回调,初始启动时也要做一次检测:
let networkInfo = CTTelephonyNetworkInfo() // 应用启动时先检测一次 checkSIMStatus() // 监听SIM卡状态变化,变化时自动触发检测 networkInfo.subscriberCellularProviderDidUpdateNotifier = { [weak self] _ in self?.checkSIMStatus() } // 核心检测逻辑 func checkSIMStatus() { guard let carrier = networkInfo.subscriberCellularProvider else { // 没有SIM卡,弹出提示并限制应用 showSIMRequiredAlert() lockAppFunctionality() return } // 有些情况下carrier对象存在,但属性为空,也说明无SIM卡 if carrier.carrierName == nil || carrier.mobileNetworkCode == nil || carrier.mobileCountryCode == nil { showSIMRequiredAlert() lockAppFunctionality() } else { // 有SIM卡,恢复应用正常使用 unlockAppFunctionality() } } // 弹出提示框 func showSIMRequiredAlert() { let alert = UIAlertController(title: "提示", message: "请插入SIM卡才能使用本应用", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "知道了", style: .default)) // 获取当前顶层ViewController弹出提示 if let topVC = UIApplication.shared.connectedScenes .filter({$0.activationState == .foregroundActive}) .compactMap({$0 as? UIWindowScene}) .first?.windows .filter({$0.isKeyWindow}).first?.rootViewController { topVC.present(alert, animated: true) } } // 限制应用功能(比如跳转到引导页、禁用所有交互) func lockAppFunctionality() { // 这里根据你的应用需求实现具体限制逻辑,比如: // let lockVC = LockViewController() // UIApplication.shared.keyWindow?.rootViewController = lockVC } // 恢复应用正常功能 func unlockAppFunctionality() { // 恢复正常的根ViewController或启用交互逻辑 }
- 注意事项:
- 需要在Info.plist中添加
NSCellularNetworkUsageDescription键,填写应用使用蜂窝网络的原因(比如“检测SIM卡状态以确保应用正常运行”),否则可能在部分iOS版本上崩溃或权限被拒。 subscriberCellularProviderDidUpdateNotifier从iOS 12开始可用,如果需要兼容iOS 12以下版本,可以额外监听CTRadioAccessTechnologyDidChange通知(虽然废弃,但旧系统仍能触发),但优先使用前者。
- 需要在Info.plist中添加
内容的提问来源于stack exchange,提问作者Shakthi
相关产品推荐
相关产品推荐

