如何判断iOS中是否启用或禁用“移动网络数据”(即使通过WiFi连接)?

时间:2017-03-23 07:43:04

标签: ios objective-c swift networking cellular-network

我有一个应用程序,我希望能够在某个特定时间间隔后获取连接状态报告。 即使我连接或关联到Wifi网络,我也想知道是否通过蜂窝网络启用了数据访问。这意味着,如果经过检查,我可以优雅地解除与wifi网络的关联,因为知道设备将连接到的可用蜂窝连接。

当前的可达性方法只会在我连接到该方法时向我提供有关蜂窝可用性的信息,并且在实际连接到接口之前没有太多关于获取此数据的信息。

寻找Android中可用的类似解决方案,如link中所述。

澄清

我不想看看我的设备是否具有蜂窝功能。我正在尝试确定用户是否通过移动网络启用/禁用了数据访问,并且即使我连接到Wifi也想知道此信息。用户可以通过转到“设置”来打开和关闭此功能。

6 个答案:

答案 0 :(得分:3)

应用程序无法通过该API查询是否启用了移动数据。您可以使用CTCellularData的cellularDataRestrictionDidUpdateNotifier和restrictedState来了解用户是否已启用或禁用应用程序的蜂窝数据访问。这是iOS允许的最大应用程序。即使这样也不可靠,就好像你从设备上删除了它,它仍然会给你早期的受限状态。

答案 1 :(得分:1)

我认为你必须重新思考你计划的任何事情:你永远无法确定在未来的任何时间点是否有可靠的(数据)连接:

  • 用户可能已通过其移动电话提供商禁用数据传输,因此如果WiFi关闭,蜂窝连接仍然无法提供数据。
  • 或者用户可以立即在设置中更改此内容。
  • 或者,当WiFi断开连接(进入屏蔽室或某人)时,蜂窝连接可能会在同一时刻关闭。
  • 还有更多的事情可能发生,同时在秘密房间里

您只需要处理断开连接并在这种情况下提供一个仁慈的行为(而不是例如崩溃)。

答案 2 :(得分:1)

如果您的目标是iOS 12或更高版本,则Apple引入了tomcat_folder/webapps/application/WEB-INF/lib类(作为Network框架的一部分)。 您可以(就像我一样)实例化两个不同的监视器,一个用于蜂窝网络,另一个用于无线网络:

NWPathMonitor

假设您有一个使用两个简单的布尔值跟踪两个连接状态的类,可以使用let wifiMonitor = NWPathMonitor(requiredInterfaceType: .wifi) let cellularMonitor = NWPathMonitor(requiredInterfaceType: .cellular) 属性:

pathUpdateHandler

,然后按照自己的意愿进行处理。 请记住通过调用wifiMonitor.pathUpdateHandler = { path in self.isWifiConnected = path.status == .satisfied } cellularMonitor.pathUpdateHandler = { path in self.isCellularConnected = path.status == .satisfied } 并提供串行队列来启动监视器(我提供了两个单独的队列); 有一个怪癖,因此,一旦取消监视器实例,就必须实例化一个新实例,因为它无法重新启动。

答案 3 :(得分:0)

https://github.com/ashleymills/Reachability.swift 可达性有一种方法来确定网络是否可通过WWAN访问

var isReachableViaWWAN: Bool {
    // Check we're not on the simulator, we're REACHABLE and check we're on WWAN
    return isRunningOnDevice && isReachableFlagSet && isOnWWANFlagSet
}

答案 4 :(得分:0)

我的解决方案看上去有点像“过大杀伤力”,也许有人觉得它有用。 但是这个想法是要考虑到用户的蜂窝数据应用程序设置。 它利用单例避免两次启动,并使BOOL依赖并发布可以在应用程序中任何位置观察到的Notification。

//  MobileDataPolicy.h
#ifndef MobileDataPolicy_h
#define MobileDataPolicy_h

#import <Foundation/Foundation.h>
@import CoreTelephony;

NS_ASSUME_NONNULL_BEGIN

extern NSNotificationName const kMobileDataPolicyNotification;
extern NSString * const kMobileDataPolicyAllowedKey;

@interface MobileDataPolicy : NSObject
+(BOOL)isAllowed;
@end

NS_ASSUME_NONNULL_END

#endif

//  MobileDataPolicy.m
#import "MobileDataPolicy.h"

NSNotificationName const kMobileDataPolicyNotification = @"kMobileDataPolicyNotification";
NSString * const kMobileDataPolicyAllowedKey = @"kMobileDataPolicyAllowedKey";

@interface MobileDataPolicy ()
@property (nonatomic, readwrite) BOOL cellularDataAllowed;
@end

@implementation MobileDataPolicy

+(instancetype)singleton {
    static MobileDataPolicy * singletonInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if ( !singletonInstance ) {
            singletonInstance = [[MobileDataPolicy alloc] initReal];
            if (singletonInstance) {
                [singletonInstance setupCellularDataPolicyHandler];
            }
        }
    });
    return singletonInstance;
}

_Pragma("clang diagnostic push")
_Pragma("clang diagnostic ignored \"-Wobjc-designated-initializers\"")
-(instancetype)init {
    NSAssert(NO, @"init is not the designated initializer for instances of MobileDataPolicy. use [MobileDataPolicy isAllowed]");
    return nil;
}
_Pragma("clang diagnostic pop")

-(instancetype)initReal {
    if (!(self=[super init])) return nil;
    _cellularDataAllowed = NO;
    return self;
}

// ask for policy with [MobileDataPolicy allowed]
+(BOOL)isAllowed {
    //we need only one handler per App.
    return [MobileDataPolicy singleton].cellularDataAllowed;
}

#pragma mark setup - Cellular Data Policy Handler
- (void)setupCellularDataPolicyHandler {
    if (@available(iOS 9.0, *)) {
        CTCellularData *cellularData = [[CTCellularData alloc] init];
        
        //following handler block will run on default priority global dispatch queue
        [cellularData setCellularDataRestrictionDidUpdateNotifier:^(CTCellularDataRestrictedState state) {
            switch (state) {
                case kCTCellularDataRestrictedStateUnknown: self->_cellularDataAllowed = NO;
                    break;
                case kCTCellularDataRestricted: self->_cellularDataAllowed = NO;
                    break;
                case kCTCellularDataNotRestricted: self->_cellularDataAllowed = YES;
                    break;
                default:
                    break;
            }
            [[NSNotificationCenter defaultCenter] postNotificationName:kMobileDataPolicyNotification object:nil userInfo:@{kMobileDataPolicyAllowedKey:@(state)}];
        }];
    }
}
@end

在示例中使用。

 //class method that inits singleton and returns state
 BOOL reachCellularData = MobileDataPolicy.isAllowed;
 NSLog(@"initial cellular data allowed for app = %@",reachCellularData ? @"YES" : @"NO");
 
 //start observing
 id<NSObject> noteKeeper = [[NSNotificationCenter defaultCenter] addObserverForName:kMobileDataPolicyNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note) {
     // do something on cellular Data Policy State change..
     int cellularDataState = [note.userInfo[kMobileDataPolicyAllowedKey] intValue];
 }];
 
 //stop observing, possibly in -(void)dealloc
 [[NSNotificationCenter defaultCenter] removeObserver:noteKeeper];

答案 5 :(得分:-1)

你可以知道所有场景:

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNetworkChange:) name:kReachabilityChangedNotification object:nil];
        Reachability *reachablity=[Reachability reachabilityWithHostName:@"google.com"];

        [reachablity startNotifier];

        //    reachablity = [Reachability reachabilityForInternetConnection];

        NetworkStatus remoteHostStatus = [reachablity currentReachabilityStatus];
        if(remoteHostStatus == NotReachable) {
            NSLog(@"network not available ");


        }
        else if (remoteHostStatus == ReachableViaWiFi) {
            NSLog(@"connect with wifi");


        }
        else if (remoteHostStatus == ReachableViaWWAN) {
            NSLog(@"Cellulor network ");


        }
        return netwrokCheck;