我的iOS应用如何判断蜂窝数据是否已禁用?

19

我有一个iOS应用程序,在应用程序启动时会进行一些小的网络请求(资源更新等)。如果用户在iOS设置中关闭了该应用程序的蜂窝数据访问权限,每次启动时他们都会收到iOS关于网络使用的提示。是否有一种编程方式可以知道此应用程序的蜂窝数据已被禁用,以便我可以在启动时禁用这些请求?


你可以使用可达性类。 - Woodstock
1
可达性检测对此无效,它错误地报告为“可达”。https://dev59.com/14Tba4cB1Zd3GeqP3UCq - cat
7个回答

13

所以我从苹果开发者论坛上找到了一位苹果工程师的回答(https://devforums.apple.com/message/1059332#1059332)。

另一位开发者写信给DTS,所以我有机会对此进行深入调查。不幸的是,新闻和我预期的一样:没有支持的方法来检测您的应用程序是否处于这种状态。也没有办法进行“无用户交互”网络连接,也就是说,请求失败而不是显示这样的UI。如果这些限制对您的应用程序造成问题,我鼓励您提交错误报告,描述您的具体要求。
https://developer.apple.com/bug-reporting/

所以看来无法检测您的应用程序的蜂窝数据是否被关闭。

编辑

我提交了一个错误报告,并请求添加这个功能。我刚刚在我的错误报告中收到了这个通知。

我们认为这个问题已经在最新的iOS 9测试版中得到解决。

我查看了API差异,但目前还没有找到新的API。


糟糕,Marco Arment似乎遇到了同样的问题(https://twitter.com/marcoarment/status/528753787033628672及其周围的推文)。 - Tom Hamming
3
iOS 9中苹果所做的“修复”是将SCNetworkReachabilityFlags标志设置为未定义值0,而不是kSCNetworkReachabilityFlagsReachable。 - Casey
1
此功能可在iOS9或更高版本中使用CTCellularData。 - Paul King

10

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将返回应用程序状态为“未受限制”。


2
总是得到“restrictedStateUnknown”。 - jaya raj

5

我想为未来的旅行者增加一份上面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;
        }];
    }
}

1
我发现 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.
            }
        }
    }
}

0

-1

2
即使用户已经禁用了应用程序的蜂窝数据使用,该应用程序仍将报告通过 WWAN 可达。 - Scott H

-2

有很多框架可以提供您的网络连接状态,当然您也可以自己编写。我发现AFNetworking是最好的之一。它有一个名为AFNetworkReachabilityManager的单例类,可以为您抽象出一些复杂性。具体来说,您需要查看两个布尔属性:

reachableViaWWAN
reachableViaWiFi 

还有一个可设置的可达性状态变化块:

 setReachabilityStatusChangeBlock:

AFNetworking Github

AFNetworkReachabilityManager


这是与编程相关的内容。

3
可达性检测对此无效,它会错误地报告“可达”。https://dev59.com/14Tba4cB1Zd3GeqP3UCq - cat

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