您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關如何在iOS中實時檢測網絡狀態,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
前言
在網絡應用中,需要對用戶設備的網絡狀態進行實時監控,有兩個目的:
(1)讓用戶了解自己的網絡狀態,防止一些誤會(比如怪應用無能)
(2)根據用戶的網絡狀態進行智能處理,節省用戶流量,提高用戶體驗
WIFI\3G網絡:自動下載高清圖片
低速網絡:只下載縮略圖
沒有網絡:只顯示離線的緩存數據
示例代碼
Reachability.h頭文件代碼:
#import <Foundation/Foundation.h> #import <SystemConfiguration/SystemConfiguration.h> #import <netinet/in.h> //http://www.cnblogs.com/xiaofeixiang typedef 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 1 static 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 NO SCNetworkReachabilityRef _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 voidvoid *)(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; } }
看完上述內容,你們對如何在iOS中實時檢測網絡狀態有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。