CTServiceRadioAccessTechnologyDidChange notification not accurate

I have a singleton observing CTServiceRadioAccessTechnologyDidChange notification from there we unwrap telephonyInfo.serviceCurrentRadioAccessTechnology dictionary with notification.object and then compare to Radio Access Tech friendly names.

We do the above to detect when device changes from 3G to 4G (that is the end goal) but the notification does not consistent update.

When testing on device we switch in Settings -> Cellular -> Cellular Data Options -> Voice & Data between LTE and 3G and at times the notification does not accurate reflect when device switches to 3G or back to LTE, it gets stuck in 3G or LTE.

Below is the code implementation:

func initializeRadioAccessMonitor() {

        let carrierType = telephonyInfo.serviceCurrentRadioAccessTechnology

        if let radioTech = carrierType?.first?.value {
            self.classifyRadioAccessTech(identifier: radioTech)
        }

        NotificationCenter.default.addObserver(self, selector: #selector(radioAccessChanged), name: .CTServiceRadioAccessTechnologyDidChange, object: nil)
}

@objc func radioAccessChanged(_ notification: Notification) {

        let identifier = notification.object as! String

        if let radioAccess = telephonyInfo.serviceCurrentRadioAccessTechnology?[identifier] {

            self.classifyRadioAccessTech(identifier: radioAccess)

        } else {

            print("[DEBUG] Error unable to unwrap radio access")

        }
    }

func classifyRadioAccessTech(identifier: String) {

        print("[DEBUG] Radio Access technology: \(identifier)")

        if #available(iOS 14.1, *) {

            switch identifier {

            case CTRadioAccessTechnologyGPRS, CTRadioAccessTechnologyEdge:

                radioAccessSpeed = .lowSpeed

            case CTRadioAccessTechnologyLTE:

                radioAccessSpeed = .highSpeed

            case CTRadioAccessTechnologyNRNSA, CTRadioAccessTechnologyNR:

                radioAccessSpeed = .superSpeed

            default:

                radioAccessSpeed = .mediumSpeed

            }

        } else {

            switch identifier {

            case CTRadioAccessTechnologyGPRS, CTRadioAccessTechnologyEdge:

                radioAccessSpeed = .lowSpeed

            case CTRadioAccessTechnologyLTE:

                radioAccessSpeed = .highSpeed

            default:

                radioAccessSpeed = .mediumSpeed

            }
        }
    }

Am I observing the wrong notification or is there a better way to detect changes between 3G and 4G.

System details: Xcode 13.0

Device details: iPad 6th Gen LTE - PadOS 15 iPad 8th Gen LTE - PadOS 14.7.1

Accepted Reply

In your snippet I’m presuming that telephonyInfo is a reference to an CTTelephonyNetworkInfo object. What’s the lifetime of that reference? It seems that you’re stashing it in a property, meaning that it persists for a long time. Is that right?

If so, try tweaking your code to tear down and re-create your CTTelephonyNetworkInfo setup, including the notification, when you come back from being suspended. Historically CT had problems where its CTTelephonyNetworkInfo objects would disconnect from its back end after a suspension. I’m not sure whether that’s the case here, but it’s worth a shot.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • I think that did it, thank you very much. Will need to do more testing but it appears to be more stable. Thank you again!

Add a Comment

Replies

In your snippet I’m presuming that telephonyInfo is a reference to an CTTelephonyNetworkInfo object. What’s the lifetime of that reference? It seems that you’re stashing it in a property, meaning that it persists for a long time. Is that right?

If so, try tweaking your code to tear down and re-create your CTTelephonyNetworkInfo setup, including the notification, when you come back from being suspended. Historically CT had problems where its CTTelephonyNetworkInfo objects would disconnect from its back end after a suspension. I’m not sure whether that’s the case here, but it’s worth a shot.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

  • I think that did it, thank you very much. Will need to do more testing but it appears to be more stable. Thank you again!

Add a Comment

I think that did it

Cool.

I’d appreciate you filing a bug about this. IMO CT should either not have this limitation or this limitation should be documented clearly.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"