iOS開發-Reachability即時檢測Wifi,2G/3G/4G/網路狀態

來源:互聯網
上載者:User

標籤:

最近遇到一個功能就是根據使用者當前的網路狀,使用者未連網需要提示一下,如果是Wifi可以推薦一些圖片新聞,如果是3G模式設定為無圖的模式,擷取網路狀態比較簡單,畢竟中國現在的流量還是一個比較貴的狀態,哪天使用者發現App消耗流量過多說不定就幹掉了App。不過蘋果的Reachability都解決了以上問題,使用起來也比較方便,具體的稍微簡單分析一下。

Reachability.h標頭檔代碼:

 

#import <Foundation/Foundation.h>#import <SystemConfiguration/SystemConfiguration.h>#import <netinet/in.h>//http://www.cnblogs.com/xiaofeixiangtypedef enum : NSInteger {NotReachable = 0,ReachableViaWiFi,ReachableViaWWAN} NetworkStatus;extern NSString *kReachabilityChangedNotification;@interface Reachability : NSObject/*! * Use to check the reachability of a given host name. */+ (instancetype)reachabilityWithHostName:(NSString *)hostName;/*! * Use to check the reachability of a given IP address. */+ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;/*! * Checks whether the default route is available. Should be used by applications that do not connect to a particular host. */+ (instancetype)reachabilityForInternetConnection;/*! * Checks whether a local WiFi connection is available. */+ (instancetype)reachabilityForLocalWiFi;/*! * Start listening for reachability notifications on the current run loop. */- (BOOL)startNotifier;- (void)stopNotifier;- (NetworkStatus)currentReachabilityStatus;/*! * WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand. */- (BOOL)connectionRequired;@end

 

Reachability.m檔案:

#import <arpa/inet.h>#import <ifaddrs.h>#import <netdb.h>#import <sys/socket.h>#import <CoreFoundation/CoreFoundation.h>#import "Reachability.h"NSString *kReachabilityChangedNotification = @"kNetworkReachabilityChangedNotification";#pragma mark - Supporting functions#define kShouldPrintReachabilityFlags 1static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment){#if kShouldPrintReachabilityFlags    NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",          //當前網路2G/3G/4G蜂窩網路          (flags & kSCNetworkReachabilityFlagsIsWWAN)? ‘W‘ : ‘-‘,          //網路是否可達          (flags & kSCNetworkReachabilityFlagsReachable)            ? ‘R‘ : ‘-‘,          (flags & kSCNetworkReachabilityFlagsTransientConnection)  ? ‘t‘ : ‘-‘,          (flags & kSCNetworkReachabilityFlagsConnectionRequired)   ? ‘c‘ : ‘-‘,          (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic)  ? ‘C‘ : ‘-‘,          (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? ‘i‘ : ‘-‘,          (flags & kSCNetworkReachabilityFlagsConnectionOnDemand)   ? ‘D‘ : ‘-‘,          (flags & kSCNetworkReachabilityFlagsIsLocalAddress)       ? ‘l‘ : ‘-‘,          (flags & kSCNetworkReachabilityFlagsIsDirect)             ? ‘d‘ : ‘-‘,          comment          );#endif}static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info){#pragma unused (target, flags)NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");NSCAssert([(__bridge NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");    //http://www.cnblogs.com/xiaofeixiang    Reachability* noteObject = (__bridge Reachability *)info;    // Post a notification to notify the client that the network reachability changed.    [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];}#pragma mark - Reachability implementation@implementation Reachability{BOOL _alwaysReturnLocalWiFiStatus; //default is NOSCNetworkReachabilityRef _reachabilityRef;}//通過網域名稱進行執行個體化  部落格園-Fly_Elephant+ (instancetype)reachabilityWithHostName:(NSString *)hostName{Reachability* returnValue = NULL;SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);if (reachability != NULL){returnValue= [[self alloc] init];if (returnValue != NULL){returnValue->_reachabilityRef = reachability;returnValue->_alwaysReturnLocalWiFiStatus = NO;}}return returnValue;}//通過ip地址執行個體化Reachability+ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress{SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)hostAddress);Reachability* returnValue = NULL;if (reachability != NULL){returnValue = [[self alloc] init];if (returnValue != NULL){returnValue->_reachabilityRef = reachability;returnValue->_alwaysReturnLocalWiFiStatus = NO;}}return returnValue;}//檢測是否能夠直接連上互連網+ (instancetype)reachabilityForInternetConnection{struct sockaddr_in zeroAddress;bzero(&zeroAddress, sizeof(zeroAddress));zeroAddress.sin_len = sizeof(zeroAddress);zeroAddress.sin_family = AF_INET;    return [self reachabilityWithAddress:&zeroAddress];}//檢測當前網路是否能夠聯上wifi+ (instancetype)reachabilityForLocalWiFi{struct sockaddr_in localWifiAddress;bzero(&localWifiAddress, sizeof(localWifiAddress));localWifiAddress.sin_len = sizeof(localWifiAddress);localWifiAddress.sin_family = AF_INET;// IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0.localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);Reachability* returnValue = [self reachabilityWithAddress: &localWifiAddress];if (returnValue != NULL){returnValue->_alwaysReturnLocalWiFiStatus = YES;}    return returnValue;}#pragma mark - Start and stop notifier- (BOOL)startNotifier{BOOL returnValue = NO;SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};    //SCNetworkReachabilitySetCallback函數為指定一個target    //當裝置對於這個target連結狀態發生改變時(比如取消連結,或者重新連上),則回調reachabilityCallback函數,if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context)){if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode)){returnValue = YES;}}    return returnValue;}- (void)stopNotifier{if (_reachabilityRef != NULL){SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);}}- (void)dealloc{[self stopNotifier];if (_reachabilityRef != NULL){CFRelease(_reachabilityRef);}}#pragma mark - Network Flag Handling- (NetworkStatus)localWiFiStatusForFlags:(SCNetworkReachabilityFlags)flags{PrintReachabilityFlags(flags, "localWiFiStatusForFlags");NetworkStatus returnValue = NotReachable;if ((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect)){returnValue = ReachableViaWiFi;}    return returnValue;}- (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags{PrintReachabilityFlags(flags, "networkStatusForFlags");if ((flags & kSCNetworkReachabilityFlagsReachable) == 0){// The target host is not reachable.return NotReachable;}    NetworkStatus returnValue = NotReachable;if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0){/*         If the target host is reachable and no connection is required then we‘ll assume (for now) that you‘re on Wi-Fi...         */returnValue = ReachableViaWiFi;}if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||        (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)){        /*         ... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs...         */        if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)        {            /*             ... and no [user] intervention is needed...             */            returnValue = ReachableViaWiFi;        }    }if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN){/*         ... but WWAN connections are OK if the calling application is using the CFNetwork APIs.         */returnValue = ReachableViaWWAN;}    return returnValue;}- (BOOL)connectionRequired{NSAssert(_reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");SCNetworkReachabilityFlags flags;if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags)){return (flags & kSCNetworkReachabilityFlagsConnectionRequired);}    return NO;}//擷取當前網路狀態- (NetworkStatus)currentReachabilityStatus{NSAssert(_reachabilityRef != NULL, @"currentNetworkStatus called with NULL SCNetworkReachabilityRef");NetworkStatus returnValue = NotReachable;SCNetworkReachabilityFlags flags;    if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags)){if (_alwaysReturnLocalWiFiStatus){returnValue = [self localWiFiStatusForFlags:flags];}else{returnValue = [self networkStatusForFlags:flags];}}    return returnValue;}@end

AppDelegate中的實現:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    //添加一個系統通知    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil];    //初始化    self.internetReachability=[Reachability reachabilityForInternetConnection];    //通知添加到Run Loop    [self.internetReachability startNotifier];    [self updateInterfaceWithReachability:_internetReachability];    return YES;}

回呼函數:

- (void) reachabilityChanged:(NSNotification *)note{    Reachability* curReach = [note object];    NSParameterAssert([curReach isKindOfClass:[Reachability class]]);    [self updateInterfaceWithReachability:curReach];}- (void)updateInterfaceWithReachability:(Reachability *)reachability{    NetworkStatus netStatus = [reachability currentReachabilityStatus];    switch (netStatus) {        case NotReachable:            NSLog(@"====當前網路狀態不可達=======http://www.cnblogs.com/xiaofeixiang");            break;        case ReachableViaWiFi:            NSLog(@"====當前網路狀態為Wifi=======部落格園-Fly_Elephant");            break;        case ReachableViaWWAN:            NSLog(@"====當前網路狀態為3G=======keso");            break;    }}

 模式測試 Wifi模式-wuWifi-串連Wifi,顯示結果如下:

如果直接通過host執行個體化也可以:

    NSString *remoteHostName = @"www.cnblogs.com/xiaofeixiang";    self.hostReachability = [Reachability reachabilityWithHostName:remoteHostName];  

iOS開發-Reachability即時檢測Wifi,2G/3G/4G/網路狀態

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.