Question

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?

Was it helpful?

Solution 2

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");
        });
};

OTHER TIPS

You can check it by CTCarrier class.

enter image description here

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.

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
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top