iOS 12 上 CTTelephonyNetworkInfo 返回 nil

4

I have the following code:

let networkStatus = CTTelephonyNetworkInfo()

func getCellularInfo() {
    if #available(iOS 12.0, *) {
        var info = networkStatus.serviceSubscriberCellularProviders
        if let aKey = networkStatus.value(forKey: "serviceSubscriberCellularProvider") {
            print("aKey: \(aKey)")
        }
    }
}

这段代码返回以下结果:

aKey: { 0000000100000001 = "CTCarrier (0x28282e610) {\n\t运营商名称: [Vodacom]\n\t移动国家码: [655]\n\t移动网络码:[01]\n\tISO国家码:[za]\n\t允许VOIP? [YES]\n}\n"; }

我不熟悉这个方法,如何获取与键关联的值,例如\n\t移动国家码: [655]/n/

不要使用value(forKey:),请使用object(forKey:)。另外,根据文档所述,info[String: CTCarrier],因此您需要获取字典的值(例如,迭代字典并获取运营商),然后使用myCarrier.mobileCountryCode - Larme
你为什么要使用 value(forKey:) 呢?直接使用 networkStatus.serviceSubscriberCellularProviders 访问值不好吗,就像你已经做的那样? - Alexander
3个回答

6

CTTelephonyNetworkInfo的属性serviceSubscriberCellularProviders 返回一个由字符串键控的CTCarrier对象字典。

var serviceSubscriberCellularProviders: [String : CTCarrier]?

你可以在你的声明输出中看到:CTCarrier(0x28282e610){...}.

你的输出结果不清楚,因为你发布的代码虽然语法正确,但从未使用生成的info字典变量。

所以正确的代码应该是(假设serviceSubscriberCellularProvider是键):

let networkStatus = CTTelephonyNetworkInfo()
if let info = networkStatus.serviceSubscriberCellularProviders, 
   let carrier = info["serviceSubscriberCellularProvider"] {
    //work with carrier object
    print("MNC = \(carrier.mobileNetworkCode)")
}

但是,这似乎在运行iOS 12.0.1的单卡iPhone 7上不起作用。 serviceSubscriberCellularProviders为空。可能具有双卡硬件的新手机将有不同的反应。

然而,已弃用的属性仍然有效。

let networkStatus = CTTelephonyNetworkInfo()
if let carrier = networkStatus.subscriberCellularProvider {
    print("MNC = \(carrier.mobileNetworkCode ?? "NO CODE")")
}

我指的是你指出我正在创建一个空的CTCarrier对象的主题。 - shawn.t
解决方案似乎没有起作用,我仍然得到了空值。 - shawn.t
我已经重写了答案。你提供的代码永远不会起作用。 - Warren Burton
解决了!一直在使用 iPhone 7+ 进行开发。 - shawn.t
这是一个糟糕的答案。你使用 "serviceSubscriberCellularProvider" 作为键的假设是无效的,即使在 OP 的原始问题中,你也可以看到键是 "0000000100000001",这对于使用新 API 的任何人都没有太多意义。 - Claus Jørgensen
显示剩余7条评论

2

iOS 13 / Swift 5.1 我的个人看法

class func getTelephonyInfo()->String?{
    let networkInfo = CTTelephonyNetworkInfo()

    let currCarrierType: String?
    if #available(iOS 12.0, *) {

        let serviceSubscriberCellularProviders = networkInfo.serviceSubscriberCellularProviders

        // get curr value:
        guard let dict = networkInfo.serviceCurrentRadioAccessTechnology else{
            return nil
        }
        // as apple states
        // https://developer.apple.com/documentation/coretelephony/cttelephonynetworkinfo/3024510-servicecurrentradioaccesstechnol
        // 1st value is our string:
        let key = dict.keys.first! // Apple assures is present...

        // use it on previous dict:
        let carrierType = dict[key]

        // to compare:
        guard let carrierType_OLD = networkInfo.currentRadioAccessTechnology else {
            return nil
        }
        currCarrierType = carrierType

    } else {
        // Fall back to pre iOS12
        guard let carrierType = networkInfo.currentRadioAccessTechnology else {
            return nil
        }
        currCarrierType = carrierType
    }


    switch currCarrierType{
    case CTRadioAccessTechnologyGPRS:
        return "2G" + " (GPRS)"

    case CTRadioAccessTechnologyEdge:
        return "2G" + " (Edge)"

    case CTRadioAccessTechnologyCDMA1x:
        return "2G" + " (CDMA1x)"

    case CTRadioAccessTechnologyWCDMA:
        return "3G" + " (WCDMA)"

    case CTRadioAccessTechnologyHSDPA:
        return "3G" + " (HSDPA)"

    case CTRadioAccessTechnologyHSUPA:
        return "3G" + " (HSUPA)"

    case CTRadioAccessTechnologyCDMAEVDORev0:
        return "3G" + " (CDMAEVDORev0)"

    case CTRadioAccessTechnologyCDMAEVDORevA:
        return "3G" + " (CDMAEVDORevA)"

    case CTRadioAccessTechnologyCDMAEVDORevB:
        return "3G" + " (CDMAEVDORevB)"

    case CTRadioAccessTechnologyeHRPD:
        return "3G" + " (eHRPD)"

    case CTRadioAccessTechnologyLTE:
        return "4G" + " (LTE)"

    default:
        break;
    }

    return "newer type!"
}

1
苹果不保证serviceCurrentRadioAccessTechnology返回的字典不为空。如果在没有SIM卡的iPhone上运行该代码,它实际上会崩溃,因为它返回一个空字典([:])。 - elitalon
你可以写。这只是一个带有一些针对nil和类似情况的测试的代码示例。可以进行优化。 - ingconti

0

Swift 5 / iOS 15.5 处理双卡

import CoreTelephony 

let networkStatus = CTTelephonyNetworkInfo()
if let info = networkStatus.serviceSubscriberCellularProviders, let carrier1 = info["0000000100000001"], let carrier2 = info["0000000100000002"] {
   print(carrier1.mobileCountryCode)
   print(carrier1.isoCountryCode)
   print(carrier2.mobileCountryCode)
   print(carrier2.isoCountryCode)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接