我有一个iOS应用程序,在应用程序启动时会进行一些小的网络请求(资源更新等)。如果用户在iOS设置中关闭了该应用程序的蜂窝数据访问权限,每次启动时他们都会收到iOS关于网络使用的提示。是否有一种编程方式可以知道此应用程序的蜂窝数据已被禁用,以便我可以在启动时禁用这些请求?
我有一个iOS应用程序,在应用程序启动时会进行一些小的网络请求(资源更新等)。如果用户在iOS设置中关闭了该应用程序的蜂窝数据访问权限,每次启动时他们都会收到iOS关于网络使用的提示。是否有一种编程方式可以知道此应用程序的蜂窝数据已被禁用,以便我可以在启动时禁用这些请求?
所以我从苹果开发者论坛上找到了一位苹果工程师的回答(https://devforums.apple.com/message/1059332#1059332)。
另一位开发者写信给DTS,所以我有机会对此进行深入调查。不幸的是,新闻和我预期的一样:没有支持的方法来检测您的应用程序是否处于这种状态。也没有办法进行“无用户交互”网络连接,也就是说,请求失败而不是显示这样的UI。如果这些限制对您的应用程序造成问题,我鼓励您提交错误报告,描述您的具体要求。
https://developer.apple.com/bug-reporting/
所以看来无法检测您的应用程序的蜂窝数据是否被关闭。
编辑
我提交了一个错误报告,并请求添加这个功能。我刚刚在我的错误报告中收到了这个通知。
我们认为这个问题已经在最新的iOS 9测试版中得到解决。
我查看了API差异,但目前还没有找到新的API。
iOS9及以后版本,使用苹果的CTCellularData类,可以检查设置以启用/禁用应用程序的蜂窝数据(设置/蜂窝移动网络/App名称)。下面的代码将在初始运行时设置cellularDataRestrictedState,然后每当更改时都会设置并记录:
import CoreTelephony
var cellularDataRestrictedState = CTCellularDataRestrictedState.restrictedStateUnknown
let cellState = CTCellularData.init()
cellState.cellularDataRestrictionDidUpdateNotifier = { (dataRestrictedState) in
if cellularDataRestrictedState != .restrictedStateUnknown { // State has changed - log to console
print("cellularDataRestrictedState: " + "\(dataRestrictedState == .restrictedStateUnknown ? "unknown" : dataRestrictedState == .restricted ? "restricted" : "not restricted")")
}
cellularDataRestrictedState = dataRestrictedState
}
很不幸的是(截至iOS11),此API似乎仅检查应用程序开关的状态 - 如果您的应用程序开关已设置为启用,而用户将移动数据总开关切换为禁用,则此API将返回应用程序状态为“未受限制”。
我想为未来的旅行者增加一份上面Swift代码的Objective C版本。
- (void)monitorCanUseCellularData {
if (GCIsiOS9) {
CTCellularData *cellularData = [[CTCellularData alloc] init];
NSLog(@"%ld", cellularData.restrictedState);
// 0, kCTCellularDataRestrictedStateUnknown
[cellularData setCellularDataRestrictionDidUpdateNotifier:^(CTCellularDataRestrictedState state) {
NSLog(@"%ld", state);
self.canUseCellularData = cellularData.restrictedState ==2?true:false;
}];
}
}
CTCellularData
类需要一些时间才能得到正确的值。在我的实现中,我在 appDidFinishLaunching
之后很早就调用了 didUpdateNotifier
。当我的网络调用返回错误时,我肯定有一个正确的限制状态值。class CellularRestriction: NSObject {
private static var cellularData = CTCellularData()
private static var currentState = CTCellularDataRestrictedState.restrictedStateUnknown
static var isRestricted: Bool {
currentState = cellularData.restrictedState
return currentState == .restricted
}
static func prepare() {
if currentState == .restrictedStateUnknown {
cellularData.cellularDataRestrictionDidUpdateNotifier = { state in
currentState = cellularData.restrictedState // This value may be inconsistent, however the next read of isRestricted should be correct.
}
}
}
}
let cellMonitor = NWPathMonitor(requiredInterfaceType: .cellular)
cellMonitor.pathUpdateHandler = { path in
self.isCellConnected = path.status == .satisfied
}
除了dirkgroten的答案,你还可以使用苹果的Reachability类,可以在这里找到:
https://developer.apple.com/Library/ios/samplecode/Reachability/Introduction/Intro.html
它使用SCNetworkReachability
,非常直观易用,它将检测通过蜂窝网络和WiFi的连接性,因为您需要在启动时检查两者。有很多框架可以提供您的网络连接状态,当然您也可以自己编写。我发现AFNetworking
是最好的之一。它有一个名为AFNetworkReachabilityManager
的单例类,可以为您抽象出一些复杂性。具体来说,您需要查看两个布尔属性:
reachableViaWWAN
reachableViaWiFi
还有一个可设置的可达性状态变化块:
– setReachabilityStatusChangeBlock: