【发布时间】:2011-07-02 23:15:41
【问题描述】:
以下代码用于确定设备是否支持电话通话是否可靠? 我担心的是,如果苹果将 iphone 字符串更改为其他任何内容,假设他们决定使用“iphone 3g”、“iphone 4”等。
[[UIDevice currentDevice].model isEqualToString:@"iPhone"]
【问题讨论】:
标签: ios objective-c iphone cocoa-touch phone-call
以下代码用于确定设备是否支持电话通话是否可靠? 我担心的是,如果苹果将 iphone 字符串更改为其他任何内容,假设他们决定使用“iphone 3g”、“iphone 4”等。
[[UIDevice currentDevice].model isEqualToString:@"iPhone"]
【问题讨论】:
标签: ios objective-c iphone cocoa-touch phone-call
根据@the-guardian 的回复,我想出了以下(迅速):
import CoreTelephony
/**
Indicates if the device can make a phone call.
- seealso: [Source](http://stackoverflow.com/a/11595365/3643020)
- returns: `true` if the device can make a phone call. `false` if not.
*/
final class func canMakePhoneCall() -> Bool {
guard let url = URL(string: "tel://") else {
return false
}
let mobileNetworkCode = CTTelephonyNetworkInfo().subscriberCellularProvider?.mobileNetworkCode
let isInvalidNetworkCode = mobileNetworkCode == nil
|| mobileNetworkCode?.count == 0
|| mobileNetworkCode == "65535"
return UIApplication.shared.canOpenURL(url)
&& !isInvalidNetworkCode
}
此代码已在 iPad Air 2 Wifi、iPad Air 2 模拟器、iPhone 6S Plus 上进行了测试,并且似乎可以正常工作。很快将确定在带有移动数据的 iPad 上。
【讨论】:
如果您要求拨打电话号码并显示 没有电话的设备上的错误:
void openURL(NSURL *url, void (^ __nullable completionHandler). (BOOL success))
{
if (@available(iOS 10.0, *)) {
[application openURL:url options:@{} completionHandler:^(BOOL success) {
completionHandler(success);
}];
} else
{
if([application openURL:url]) {
completionHandler(YES);
} else {
completionHandler(NO);
}
}
}
用法
p97openURL(phoneURL, ^(BOOL success) {
if(!success) {
show message saying there is no telephony on device
}
}
【讨论】:
这个UIApplication.shared.openURL((URL(string: "tel://\(phoneNumber)")!)) 不会说它是否有 SIM 卡这只会说设备是否有拨打电话的选项。 例如:有或没有 SIM 卡的 iPhone 都会返回 true,但在 iPod Touch 中它总是会返回 false,就像 ipad 没有 sim 选项它会返回 false 一样。 p>
这是全面检查所有内容的代码!(使用 Swift 3.0)
if UIApplication.shared.canOpenURL(URL(string: "tel://\(phoneNumber)")!) {
var networkInfo = CTTelephonyNetworkInfo()
var carrier: CTCarrier? = networkInfo.subscriberCellularProvider
var code: String? = carrier?.mobileNetworkCode
if (code != nil) {
UIApplication.shared.openURL((URL(string: "tel://\(phoneNumber)")!))
}
else {
var alert = UIAlertView(title: "Alert", message: "No SIM Inserted", delegate: nil, cancelButtonTitle: "ok", otherButtonTitles: "")
alert.show()
}
}
else {
var alert = UIAlertView(title: "Alert", message: "Device does not support phone calls.", delegate: nil, cancelButtonTitle: "ok", otherButtonTitles: "")
alert.show()
}
通过这种方式,我们可以确定设备是否支持通话。
【讨论】:
根据@TheGuardian 的回答,我认为这可能是一种更简单的方法:
private final func canMakePhoneCall() -> Bool {
guard UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Phone else {
return false
}
let mobileNetworkCode = CTTelephonyNetworkInfo().subscriberCellularProvider?.mobileNetworkCode
let isInvalidNetworkCode = mobileNetworkCode == nil || mobileNetworkCode?.characters.count <= 0
|| mobileNetworkCode == "65535"
//When sim card is removed, the Code is 65535
return !isInvalidNetworkCode
}
【讨论】:
仅检查设备是否“支持”电话呼叫可能不是处理事情的最佳方式,具体取决于您要完成的任务。信不信由你,有些人在没有维修服务的情况下使用旧 iPhone,就好像它们是 iPod Touch 一样。有时人们的 iPhone 中没有安装 SIM 卡。在我的应用程序中,如果用户设备能够拨打电话号码,我想拨打电话号码,否则我想显示电话号码并提示用户拿起电话并拨打电话。这是我想出的一个迄今为止有效的解决方案。随意评论和改进它。
// You must add the CoreTelephony.framework
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CoreTelephony/CTCarrier.h>
-(bool)canDevicePlaceAPhoneCall {
/*
Returns YES if the device can place a phone call
*/
// Check if the device can place a phone call
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tel://"]]) {
// Device supports phone calls, lets confirm it can place one right now
CTTelephonyNetworkInfo *netInfo = [[[CTTelephonyNetworkInfo alloc] init] autorelease];
CTCarrier *carrier = [netInfo subscriberCellularProvider];
NSString *mnc = [carrier mobileNetworkCode];
if (([mnc length] == 0) || ([mnc isEqualToString:@"65535"])) {
// Device cannot place a call at this time. SIM might be removed.
return NO;
} else {
// Device can place a phone call
return YES;
}
} else {
// Device does not support phone calls
return NO;
}
}
您会注意到我检查了 mobileNetworkCode 是否为 65535。在我的测试中,当您移除 SIM 卡时,mobileNetworkCode 似乎设置为 65535。不是 100% 确定这是为什么。
【讨论】:
FF 以表明该值是'不设置 [1] standards.ieee.org/content/dam/ieee-standards/standards/web/…
我需要确保来电不会中断我的客户进行的录音,所以我提示他们进入飞行模式但仍然打开 wifi。上面来自 AlBeebe 的方法在 iOS 8.1.3 上对我不起作用,但如果找到这个应该在 iOS 7 及更高版本中工作的解决方案:
您必须添加和导入 CoreTelephony.framework。
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CoreTelephony/CTCarrier.h>
如果您想跟踪更改,请在您的类上定义属性
@property (strong, nonatomic) CTTelephonyNetworkInfo* networkInfo;
初始化CTTelephonyNetworkInfo:
self.networkInfo = [[CTTelephonyNetworkInfo alloc] init];
NSLog(@"Initial cell connection: %@", self.networkInfo.currentRadioAccessTechnology);
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(radioAccessChanged) name:CTRadioAccessTechnologyDidChangeNotification object:nil];
然后你会在它改变时收到回调:
- (void)radioAccessChanged {
NSLog(@"Now you're connected via %@", self.networkInfo.currentRadioAccessTechnology);
}
currentRadioAccessTechnology 的值定义在
CTTelephonyNetworkInfo.h,当没有手机信号塔连接时,您将返回 null / nil。
这是我找到它的地方:http://www.raywenderlich.com/48001/easily-overlooked-new-features-ios-7
【讨论】:
我认为通常是这样。我会进行更通用的字符串比较(只是为了在将来更新时更安全)。我使用它没有任何问题(到目前为止......)。
如果您想更确定设备是否可以实际拨打电话,您还应该利用 Core Telephony API。 CTCarrier 类可以告诉您是否真的可以在任何特定时刻拨打电话。
【讨论】:
iPhone 支持 tel:// URI 方案。所以你可以使用:
[[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tel://"]];
canOpenURL:明确检查是否有应用程序能够打开该 URL 方案,而不是 URL 是否正确。因此,没有指定电话号码并不重要。该方法返回一个 BOOL,因此请检查 YES 或 NO。
这应该从字面上回答是否存在任何能够拨打电话的应用程序。因此,它应该可以应对未来设备细分的任何变化。
【讨论】:
我认为您的方法不可靠,因为设备名称将来可能会更改。如果您担心阻止应用程序在非 iPhone 设备上运行,您可以将“电话”添加到 Info.plist 中的 UIRequiredDeviceCapabilities 字典中。这将禁止 iPhone 以外的设备从 App Store 下载您的应用。
或者,如果您需要在特定时刻检查 3G 连接,您可以使用 Apple 的 Reachability 实用程序类来询问当前的 3G/WIFI 连接状态。
【讨论】: