简体   繁体   中英

Possible way to detect sim card detection in ios?

I have a iphone app that has the capability to send messages. I want to alert user when sim card is not available in iphone. So i tried below three function to check sim card availabilty

Class messageClass = (NSClassFromString(@"MFMessageComposeViewController"));
if([messageClass canSendText]){
    // Sim available
    NSLog(@"Sim available");
}
else{
    //Sim not available
    NSLog(@"Sim not available");
}

if([MFMessageComposeViewController canSendText]){
    // Sim available
    NSLog(@"Sim available");
}
else{
    //Sim not available
    NSLog(@"Sim not available");
}

if([[UIDevice currentDevice].model isEqualToString:@"iPhone"])
{
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tel:123456"]])
    {
        NSLog(@"Sim available");
    }
    else
    {
        NSLog(@"Sim not available");
    }
}

I have checked my iphone without sim, it always return @"Sim available". But when i open default "Messages" app and try to send sms it says alert "No SIM Card Installed"... How this message app can detect sim card availabilty?

You can check it by CTCarrier class.

在此输入图像描述

BOOL isSimCardAvailable = YES;

CTTelephonyNetworkInfo* info = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier* carrier = info.subscriberCellularProvider;

if(carrier.mobileNetworkCode == nil || [carrier.mobileNetworkCode isEqualToString:@""])
{
    isSimCardAvailable = NO;
}

You need to add CoreTelephony framework for using CTTelephonyNetworkInfo and CTCarrier.

By the below code you can get the sim card details like carriername,mobilecountrycode,isocountrycode,mobilenetworkcode.In the ios 6 all are retained.So if your sim card is removed also it will retain the old details.So there this idea wont be useful but in ios 7 only carriername is retained and remaining are changed so the below code can be used

CTTelephonyNetworkInfo* info = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier* carrier = info.subscriberCellularProvider;
NSString *mobileCountryCode = carrier.mobileCountryCode;
NSString *carrierName = carrier.carrierName;
NSString *isoCountryCode = carrier.isoCountryCode;
NSString *mobileNetworkCode = carrier.mobileNetworkCode

// Try this to track CTCarrier changes 
info.subscriberCellularProviderDidUpdateNotifier = ^(CTCarrier* inCTCarrier) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"User did change SIM");
        });
};

Implemented in Swift as a read-only computed property:

import CoreTelephony

var availableSIM: Bool {
    return CTTelephonyNetworkInfo().subscriberCellularProvider?.mobileNetworkCode != nil
}

Complementing to Anneq and Felipe answers:

Swift 2.3:

import CoreTelephony
func isSimAvailable()  -> Bool {
    let info = CTTelephonyNetworkInfo()
    let carr = info.subscriberCellularProvider
    guard let carrier = carr else {
        return false
    }
    guard let carrierCode = carrier.mobileNetworkCode else {
        return false
    }
    guard carrierCode != "" else {
        return false
    }
    return true
}

Complementing the Anneq Anwar answer, here the swift version:

import CoreTelephony
func isSimAvailable()  -> Bool {
    var isSimCardAvailable = true
    var info = CTTelephonyNetworkInfo()
    var carrier = info.subscriberCellularProvider
    if carrier != nil && carrier.mobileNetworkCode == nil || carrier.mobileNetworkCode.isEqual("") {
        isSimCardAvailable = false
    }
    return isSimCardAvailable
}

fix: The carrier can be nil in some devices

Swift 4+

var isSimCardAvailable: Bool {

    let info = CTTelephonyNetworkInfo()
    if let carrier = info.subscriberCellularProvider {
        if let code = carrier.mobileNetworkCode {
            if !code.isEmpty {
                return true
            }
        }
    }
    return false
}

Swift 5+ solution that covers regular SIM and eSIM

    func hasCellularCoverage() -> Bool {
        let networkInfo = CTTelephonyNetworkInfo()

        guard let serviceSubscriberCellularProviders = networkInfo.serviceSubscriberCellularProviders else { return false }
        let carriers = serviceSubscriberCellularProviders.values

        let validCarriers = carriers.compactMap() {
            $0.isoCountryCode
        }

        return !validCarriers.isEmpty ? true : false
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM