1.先复制Reachability代码:
.h:
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <netinet/in.h>
typedef enum : NSInteger {
NotReachable = 0,
ReachableViaWiFi,
ReachableViaWWAN
} NetworkStatus;
#pragma mark IPv6 协议支持
// Reachability完全支持IPv6协议.
extern NSString *kReachabilityChangedNotification;
@interface Reachability : NSObject
/*! * 用来检测hostName的连接状态. */
+ (instancetype)reachabilityWithHostName:(NSString *)hostName;
/*! * 用来检测IP地址的连接状态. */
+(instancetype)reachabilityWithAddress:(const struct sockaddr *)hostAddress;
/*! * 用来检测默认的连接是否可用, 被用在没有特定连接的主机. */
+ (instancetype)reachabilityForInternetConnection;
/*! *开始在当前时间循环中监听Reachability通知. */
- (BOOL)startNotifier; - (void)stopNotifier;
- (NetworkStatus)currentReachabilityStatus;
/*! * 除非连接已经建立,WWAN可用,但是却没有激活. WiFi 连结也许需要一个VPN来进行连接. */
- (BOOL)connectionRequired;
@end
.m:
#import "Reachability.h"
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
#import <sys/socket.h>
#import <netinet/in.h>
#import <CoreFoundation/CoreFoundation.h>
#import "Reachability.h"
#pragma mark IPv6 协议支持
// Reachability完全支持IPv6协议.
NSString *kReachabilityChangedNotification = @"kNetworkReachabilityChangedNotification";
#pragma mark - 支持Reachability的方法
#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",
(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 没有用的(target, flags)
NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
NSCAssert([(__bridge NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
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 Reachability
{
SCNetworkReachabilityRef _reachabilityRef;
}
+ (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;
} else {
CFRelease(reachability);
}
}
return returnValue;
}
+ (instancetype)reachabilityWithAddress:(const struct sockaddr *)hostAddress {
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, hostAddress); Reachability* returnValue = NULL;
if (reachability != NULL)
{ returnValue = [[self alloc] init];
if (returnValue != NULL) {
returnValue->_reachabilityRef = reachability;
} else {
CFRelease(reachability);
}
}
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: (const struct sockaddr *) &zeroAddress];
}
#pragma mark - 开始和结束监听通知
- (BOOL)startNotifier { BOOL returnValue = NO;
SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
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)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)){
returnValue = [self networkStatusForFlags:flags];
}
return returnValue;
}
@end
2.使用:
#import "AppDelegate.h"
#import "Reachability.h"
@interface AppDelegate ()
//定义属性
@property(nonatomic,strong)Reachability *reachability;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//创建通知
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(internetConnection) name:kReachabilityChangedNotification object:nil];
//初始化可达性
self.reachability =[Reachability reachabilityForInternetConnection];
//开始监听
[self.reachability startNotifier];
[self internetConnection];
return YES;
}
-(void)internetConnection
{ //网络连接现状
NetworkStatus status =[self.reachability currentReachabilityStatus];
switch (status) {
case NotReachable:
NSLog(@"没有网络");
break;
case ReachableViaWiFi:
NSLog(@"wifi连接");
break;
case ReachableViaWWAN:
NSLog(@"移动蜂窝网络");
break;
default:
break;
}
}
可以放在Appdelegate中,作为全局使用。也可以放在需要检测网络连接状态的地方使用。
参考:
1.https://blog.csdn.net/gezi0630/article/details/51934050