李洪强iOS开发之使用 Reachability 检测网络
1.iOS平台是按照一直有网络连接的思路来设计的,开发者利用这一特点创造了很多优秀的第三方应用。
大多数的iOS应用都需要联网,甚至有些应用严重依赖网络,没有网络就无法正常工作。
2.在你的应用尝试通过网络获取数据之前,你需要知道当前设备是否知道连接上了网络,
甚至有时候你可能还需要知道当前网路是由wifi还是由移动蜂窝网络提供的。
3.“在网络访问失败的时候,应用没有做出适当的提示”是苹果的iOS审核团队拒绝一个应用的常见理由。
苹果要求你必须先检测网络连接状态,当网络不可用的时候以某种方式告知用户,或者用其他优雅的方式进行处理。
***********************
Reachability类:
1.这个类用于检测当前网络状态,它不是SDK的一部分,可以在iOS Developer Library里找到这份代码。
从苹果网站上下载Reachability.zip文件,解压之。
2.重用Reachability类
(1)把Reachability.h和Reachability.m文件拖到项目中。
(2)添加框架:SystemConfiguration.framework。
3.同步的Reachability
(1)使用同步的方式是比较简单,导入Reachability.h头文件,然后通过代码检查网络:
#import “Reachability.h”
。。。some code omitted…
Reachability *reach = [Reachability reachabilityForInternetConnection];
NetworkStatus status = [reach currentReachabilityStatus];
(2)通过检查某个主机能否访问来判断当前网络是否可用:
Reachability *reach = [Reachability reachabilityWithHostName:@“www.apple.com”];
NetworkStatus status = [reach currentReachabilityStatus];
(3)案例:
创建一个工程,并添加Reachability.h和Reachability.m到工程中,并链接SystemConfiguration.framework.
在AppDelegate.h头文件中导入Reachability.h,并添加一个实例方法。如图:
在AppDelegate.m中这样实现:如图:
4.异步的Reachability
(1)异步的方式稍微复杂,不过通过这种方式可以来订阅实时的网络状态变化通知。导入Reachability.h头文件,然后注册一个对象来订阅网络状态变化的信息,网络状态变化的信息名称为kReachabilityChanged-Notification.如下:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reachabilityChanged:)
name:kReachabilityChangedNotification
object:nil];
(2)你需要创建一个Reachability对象实例并开始向外发布网络状态变化的消息:
Reachability *reach = [[Reachability reachabilityWithHostName:@“www.apple.com”] retain];
[reach startNotifier];
(3)当网络状态发生变化的时候,Reachability对象将调用reachabilityChanged:方法,可以在这个方法里面获取当前的网络状态,然后做相应的处理。
- (void)reachabilityChanged:(NSNotification *)notification{
Reachability *reach = [notification object];
if([reach isKindOfClass:[Reachability class]]){
NetworkStatus status = [reach currentReachabilityStatus];
//Insert your code here
}
}
****************************
5.原生 Reachability API
前面将的Reachability类实际上是苹果公司对SCNetworkReachability API的封装,这个API定义在SystemConfigure.framework库中。如果有其他特别的需求,也可以直接使用这个原生的SCNetworkReachability类。
.h 和.m文件
//-------------------------.m---------------------------------------------------
//-------------------------.m---------------------------------------------------
/*
File: Reachability.h
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <netinet/in.h>
typedef enum : NSInteger {
NotReachable = 0,
ReachableViaWiFi,
ReachableViaWWAN
} NetworkStatus;
extern NSString *kReachabilityChangedNotification;
@interface Reachability : NSObject
/*!
*
用于检查给定主机名的可达性。
*/
+ (instancetype)reachabilityWithHostName:(NSString *)hostName;
/*!
*
用来检查给定IP地址的可达性。
*/
+ (instancetype)reachabilityWithAddress:(const struct sockaddr_in *)hostAddress;
/*!
*
检查是否违约路is available。should be used by应用that do not connect to a particular主机。
*/
+ (instancetype)reachabilityForInternetConnection;
/*!
* 检查是否一个本地无线连接是可用的。
*/
+ (instancetype)reachabilityForLocalWiFi;
/*!
*开始在当前运行的循环上侦听可达性通知。
*/
- (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.
*广域网可能是可用的,但不主动到连接已经建立。无线网络可能需要连接VPN的需求。
*/
- (BOOL)connectionRequired;
@end
//-------------------------.m---------------------------------------------------
//-------------------------.m---------------------------------------------------
/*
File: Reachability.m
Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
Version: 3.5
Copyright (C) 2014 Apple Inc. All Rights Reserved.
*/
#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",
(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");
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;
}
+ (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;
}
+ (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];
}
+ (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};
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
李洪强iOS开发之使用 Reachability 检测网络的更多相关文章
- 李洪强iOS开发之添加手势
李洪强iOS开发之添加手势 02 - 添加手势
- 李洪强iOS开发之- 实现简单的弹窗
李洪强iOS开发之- 实现简单的弹窗 实现的效果: 112222222222223333333333333333
- 李洪强iOS开发之后使用XIB实现横向滚动的UIScrollView
李洪强iOS开发之后使用XIB实现横向滚动的UIScrollView 11111222
- 李洪强iOS开发之苹果使用预览截图
李洪强iOS开发之苹果使用预览截图 01 在预览的图片中选中你要截得区域 02 - command + C 03 - Command + N 04 - Command + S (保存)
- 李洪强iOS开发之通知的使用
李洪强iOS开发之通知的使用 01 - 在A中发送通知 02 - 在B中监听通知 03 - 在B中通知出发的方法 04 - 在B控制器viewDidLoad调用通知
- 李洪强iOS开发之后使用纯代码实现横向滚动的UIScrollView
李洪强iOS开发之后使用纯代码实现横向滚动的UIScrollView (VTmagic是一个实现左右滚动的控制器的框架,也可以实现此功能) 实现的效果: 01 - 创建四个控制器 02 - 定义需要 ...
- 李洪强iOS开发之 - 实现九宫格并使用SDWebImage下载图片
李洪强iOS开发之 - 实现九宫格并使用SDWebImage下载图片 源码: // // ViewController.m // 08-九宫格扩展 // // Created by 李洪强 ...
- 李洪强iOS开发之 - WebViewJavascriptBridge
李洪强iOS开发之 - WebViewJavascriptBridge 01 - JS端: 02 - iOS端 01 遵守代理协议 02 申明属性 03 开启日志 04 给哪个webview建立J ...
- 李洪强iOS开发本人集成环信的经验总结_09_处理好友请求
李洪强iOS开发本人集成环信的经验总结_09_处理好友请求 实现这种效果: 01 - 遵守处理好友请求的代理协议 02 - 设置代理 03 - 实现代理方法 04 - 实现代理中用到的方法
随机推荐
- Linux学习三部曲(之二)
新建Linux分区以及文件系统 今天,我们来聊聊在linux上建立分区和文件系统.windows系统建立分区可以借助分区工具,那么在linux分区以及文件系统又该如何操作呢? 打开secureCRT, ...
- (转)mysql、sqlserver、oracle的默认事务的隔离级别
1.mysql的默认事务的隔离级别:可重复读取(repeatable read); 2.sqlserver的默认事务的隔离级别:提交读取(read committed); 3.oracle的默认事务的 ...
- ftp上传java代码
<欢迎转载http://www.cnblogs.com/shizhongtao/p/3345826.html> 上传代码就写个简单的小例子.首先要加入jar包.commons-net-1. ...
- Fuck Flyme Theme
转载说明 本篇文章可能已经更新,最新文章请转:http://www.sollyu.com/fuck-flyme-theme/ 说明 本插件仅用于魅蓝Note, MX3, MX4, MX4 PRO它机型 ...
- Unix 进程通信基本概念
一:通信分为两类: 控制信息的传递: 低级通信 大批量数据的传递: 高级通信 二:基本的通信方式 (a)主从式通信: 通信的双方存在一种隶属关系, 其中主进程是通信过程的控制者,而从进程是通信过程的从 ...
- Linux--fedora21 PC机安装以及拨号上网和无限上网
最近回家,学习许久未用的linux,之前也是在培训的时候用的是 ubuntu ,这次回家查了下 fedora 最适合开发人员使用,所以就装了个试试.刚开始只能拨号上网,经过三天时间的各种搜索查找终于解 ...
- Web前端新人笔记之了解Jquery
与javaScript相比,Jquery更简洁.浏览器的兼容性更强,语法更灵活,对xpath的支持更强大.一个$符就可以遍历文档中各级元素.例:在页面上有一个无序列表,我们需要将所有列表项中的文本内容 ...
- JS如何获取iframe内html的body值
default页面: <html> <head> <script type="text/javascript"> window.onload=f ...
- 离线文档(DocSet)下载地址汇总
我分享的百度网盘地址,官网下载慢:http://pan.baidu.com/s/1uOBYQ 名称 下载地址 更新时间 IOS 9.2 031-43202-A.dmg 20151209 OS X 10 ...
- js判断IE6(推荐方法一)
不得不使用判断的方法 //方法1:推荐 if ( /MSIE 6/.test(navigator.userAgent)){ } //方法2: if ( navigator.appVersion.ind ...