データ通信に使っているキャリアの情報が欲しい
iPhone XS, iPhone XS Max, iPhone XR以降、nano-SIMとeSIMを使ったデュアルSIMに対応している。*1
この機能はiOS 12.1 から利用できるそうだ。
これに合わせて、CTTelephonyNetworkInfo
の API が更新された。
*2
*3
また、iOS 13からはデュアルSIMの両方で通話が利用できる。 このうちデータ通信は一つの回線だけ利用可能で、それを取得するための API が追加された。 *4
この状況下で、「いったいどのキャリアがデータ通信に使用されているのかを知りたい。」場合の話。
iOS 12.0 では新しい API からキャリア情報が得られない
そういう問題があるらしい。*5
しかし API 上は subscriberCellularProvider
は deprecated になってしまった。
軽く調べたところ解決法はすでに見つかっていて、private property によって取得できるらしい。 (deprecated なメソッドを使うのとどっちもどっちな気がしないでもない。)
- https://github.com/microsoft/appcenter-sdk-apple/issues/1905
- https://github.com/microsoft/appcenter-sdk-apple/pull/1914/files/fa504f5278f7ca98a3587479d3adcfd4d568922b
最終的にこうなる
- extension をつかって CTTelephonyNetworkInfo を拡張した。
- iOS 13.0 未満においては、キャリア情報が一つかどうかでデータ通信に使用中か判定する。
extension CTTelephonyNetworkInfo { typealias Using = Bool /// iOS のバージョンに応じてキャリア情報と、それが通信に使用可能なものか取得する var versionCompatibleServiceSubscriberCellularProviders: [(CTCarrier, Using)] { if #available(iOS 13.0, *) { // iOS 13 からデュアルSIMを同時利用可能 https://support.apple.com/ja-jp/HT209086 // データ通信に使用するSIMは iOS 13 から判別可能 https://developer.apple.com/documentation/coretelephony/cttelephonynetworkinfo/3183044-dataserviceidentifier guard let providors = self.serviceSubscriberCellularProviders else { return [] } guard providors.count > 0 else { return [] } let usingId = self.dataServiceIdentifier ?? "" return providors.map { (key: String, carrier: CTCarrier) in let using = key == usingId return (carrier, using) } } else if #available(iOS 12.1, *) { // iOS 12 から複数のSIMがありうる https://developer.apple.com/documentation/coretelephony/cttelephonynetworkinfo/3024511-servicesubscribercellularprovide // iOS 12.0 ではバグで値が得られないらしい https://stackoverflow.com/questions/52846542/why-do-servicesubscribercellularproviders-return-nil-in-ios-12 guard let providers = self.serviceSubscriberCellularProviders else { return [] } guard providers.count > 0 else { return [] } // 1件であれば使っていることが自明 let using = providers.count == 1 return providers.map { (key: String, carrier: CTCarrier) in return (carrier, using) } } else if #available(iOS 12.0, *) { // private property によって参照できるらしい // microsoft の app-center-sdk におけるissue https://github.com/microsoft/appcenter-sdk-apple/issues/1905 // microsoft の app-center-sdk にも採用されている https://github.com/microsoft/appcenter-sdk-apple/pull/1914/files/fa504f5278f7ca98a3587479d3adcfd4d568922b guard let providers = self.value(forKey: "serviceSubscriberCellularProvider") as? Dictionary<String, CTCarrier> else { return [] } guard providers.count > 0 else { return [] } // 1件であれば使っていることが自明 let using = providers.count == 1 return providers.map { (key: String, carrier: CTCarrier) in return (carrier, using) } } else { guard let carrier = self.subscriberCellularProvider else { return [] } return [(carrier, true)] } } }
参考リンク
- eSIM でデュアル SIM を活用する - Apple サポート
- subscriberCellularProvider - CTTelephonyNetworkInfo | Apple Developer Documentation
- serviceSubscriberCellularProviders - CTTelephonyNetworkInfo | Apple Developer Documentation
- dataServiceIdentifier - CTTelephonyNetworkInfo | Apple Developer Documentation
- https://stackoverflow.com/questions/52846542/why-do-servicesubscribercellularproviders-return-nil-in-ios-12
- https://github.com/microsoft/appcenter-sdk-apple/issues/1905
- https://github.com/microsoft/appcenter-sdk-apple/pull/1914/files/fa504f5278f7ca98a3587479d3adcfd4d568922b
*1:eSIM でデュアル SIM を活用する - Apple サポート
*2:subscriberCellularProvider - CTTelephonyNetworkInfo | Apple Developer Documentation
*3:serviceSubscriberCellularProviders - CTTelephonyNetworkInfo | Apple Developer Documentation
*4:dataServiceIdentifier - CTTelephonyNetworkInfo | Apple Developer Documentation
*5:https://stackoverflow.com/questions/52846542/why-do-servicesubscribercellularproviders-return-nil-in-ios-12