Reachability
来源:互联网 发布:东南大学软件测试专业 编辑:程序博客网 时间:2024/05/04 22:42
iOS SDK: Detecting Network Changes with Reachability
Solutions
Even though Apple provides sample code for monitoring changes in network availability, Apple's Reachability class is a bit outdated and doesn't support ARC (Automatic Reference Counting). If you use AFNetworking, then you may want to consider AFHTTPClient
, which also lets you monitor network interface changes.
However, my preferred solution is the wonderful Reachability class created and maintained by Tony Million. It supports ARC and leverages GCD (Grand Central Dispatch). Let me show you how to integrate Tony's Reachability class.
1. Setting Up the Project
Create a new project in Xcode by selecting the Single View Application template from the list of templates (figure 1). Name your application Reachability, enter a company identifier, set iPhone for the device family, and check Use Automatic Reference Counting. The rest of the checkboxes can be left unchecked for this project (figure 2). Tell Xcode where you want to save the project and click Create.
Figure 1: Choosing a Project Template
Figure 2: Configuring the Project
2. Integrating Reachability
Step 1: Adding the Reachability Class
Integrating Tony Million's Reachability class is trivial. Visit the project's GitHub page, download the latest version, and drag Reachability.h/.m into your Xcode project (figure 3). If you take this path, make sure to copy the class files into your Xcode project (figure 4). You can also use CocoaPods to to add Reachability to your project.
Figure 3: Adding the Reachability Class to Your Project
Figure 4: Make Sure to Copy the Class Files into Your Project
Step 2: Linking Against the System Configuration Framework
The Reachability class depends on the System Configuration framework for some of its functionality. With your project selected in the Project Navigator, select the Reachability target in the list of targets, open the Build Phases tab, and expand the Link Binary with Libraries drawer. Click the plus button and search for SystemConfiguration.framework (figure 5).
Figure 5: Link Your Project Against the System Configuration Framework
3. Reachability Basics
The Reachability
class provides two ways to monitor changes in network availability: blocks and notifications. Let me show you how this works.
Step 1: Importing Reachability.h
To keep things simple, we will add the reachability logic to the application delegate. Start by adding an import statement for Reachability.h to MTAppDelegate.m as shown below.
#import "MTAppDelegate.h"
#import "Reachability.h"
#import "MTViewController.h"
Step 2: Blocks
We first need to create an instance of the Reachability
class in application:didFinishLaunchingWithOptions:
(MTAppDelegate.m) as shown below. We then set the reachableBlock
and unreachableBlock
on the Reachability
instance. The reachableBlock
is invoked when the network availability changes from unreachable to reachable. The reverse is true for the unreachableBlock
. It is key to send the Reachability
instance a message of startNotifier
so that it knows that it should start monitoring for reachability changes. It is also important to know that the call to startNotifier
causes the Reachability
instance to retain itself, which means that you don't need to store a reference to the Reachability
object. However, I am not a fan of this approach and will show you an alternative solution a bit later.
- (
BOOL
)application:(
UIApplication
*)application
didFinishLaunchingWithOptions
:(
NSDictionary
*)launchOptions {
// Initialize Reachability
Reachability
*reachability = [
Reachability
reachabilityWithHostname
:
@"www.google.com"
];
reachability
.reachableBlock
= ^(
Reachability
*reachability) {
NSLog(
@"Network is reachable."
);
};
reachability
.unreachableBlock
= ^(
Reachability
*reachability) {
NSLog(
@"Network is unreachable."
);
};
// Start Monitoring
[reachability
startNotifier
];
// Initialize View Controller
self
.viewController
= [[
MTViewController
alloc
]
initWithNibName
:
@"MTViewController"
bundle
:nil
];
// Initialize Window
self
.window
= [[
UIWindow
alloc
]
initWithFrame
:[[
UIScreen
mainScreen
]
bounds
]];
// Configure Window
[
self
.window
setRootViewController
:
self
.viewController
];
[
self
.window
makeKeyAndVisible
];
return
YES
;
}
Before we take a look at notifications, I need to stress that the reachable and unreachable blocks are invoked on a background thread. Keep this in mind when you need to update your application's user interface when the network interface changes.
Step 3: Notifications
The advantage of using notifications for reachability changes is that any object in your application can register itself as an observer for these notifications. In contrast to the use of blocks, the reachability notifications are posted and delivered on the main thread. As you can see below, in application:didFinishLaunchingWithOptions:
, we create an instance of the Reachability
class and tell it to start monitoring for network changes.
- (
BOOL
)application:(
UIApplication
*)application
didFinishLaunchingWithOptions
:(
NSDictionary
*)launchOptions {
// Initialize Reachability
Reachability
*reachability = [
Reachability
reachabilityWithHostname
:
@"www.google.com"
];
// Start Monitoring
[reachability
startNotifier
];
// Initialize View Controller
self
.viewController
= [[
MTViewController
alloc
]
initWithNibName
:
@"MTViewController"
bundle
:nil
];
// Initialize Window
self
.window
= [[
UIWindow
alloc
]
initWithFrame
:[[
UIScreen
mainScreen
]
bounds
]];
// Configure Window
[
self
.window
setRootViewController
:
self
.viewController
];
[
self
.window
makeKeyAndVisible
];
return
YES
;
}
As an example, if the view controller needs to be informed of changes in network availability, then we need to add it as an observer of the notifications the Reachability
instance posts. Open MTViewController.m
, add an import statement for Reachability.h, and update initWithNibName:bundle:
as shown below.
#import "MTViewController.h"
#import "Reachability.h"
- (
id
)initWithNibName:(
NSString
*)nibNameOrNil
bundle
:(
NSBundle
*)nibBundleOrNil {
self
= [
super
initWithNibName
:nibNameOrNil
bundle
:nibBundleOrNil];
if
(
self
) {
// Add Observer
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector
:
@selector
(reachabilityDidChange:)
name
:kReachabilityChangedNotification
object
:nil
];
}
return
self
;
}
Every time the network interface changes, reachabilityDidChange:
is invoked and the view controller can respond appropriately. The object
property of the notification is the Reachability
instance that posted the notification. The Reachability
class provides a number of useful instance methods, such as isReachable
, isReachableViaWWAN
, and isReachableViaWiFi
. You can even tell the Reachability
instance whether it should consider WWAN as unreachable by setting the reachableOnWWAN
property accordingly.
- (
void
)reachabilityDidChange:(
NSNotification
*)notification {
Reachability
*reachability = (
Reachability
*)[notification
object
];
if
([reachability
isReachable
]) {
NSLog(
@"Reachable"
);
}
else
{
NSLog(
@"Unreachable"
);
}
}
4. Reachability Manager
For applications that require a network connection, I usually use an alternative approach for managing reachability. I create a separate class named ReachabilityManager that adopts the singleton pattern. The singleton object manages a Reachability
instance and provides a number of useful class methods. Let me walk you through the internals of this class.
Step 1: Interface
As I mentioned, the MTReachabilityManager
class adopts the singleton pattern and it provides access to the singleton object through the sharedManager
class method. This is useful if an object needs direct access to the reachability
instance that the singleton object manages.
Through a number of class methods objects can ask the reachability manager about the current network interface. In addition, objects can still add themselves as observers for the kReachabilityChangedNotification
notifications as we saw earlier.
#import <Foundation/Foundation.h>
@class
Reachability
;
@interface
MTReachabilityManager
: NSObject
@property
(strong,
nonatomic
)
Reachability
*reachability;
#pragma mark -
#pragma mark Shared Manager
+ (
MTReachabilityManager
*)sharedManager;
#pragma mark -
#pragma mark Class Methods
+ (
BOOL
)isReachable;
+ (
BOOL
)isUnreachable;
+ (
BOOL
)isReachableViaWWAN;
+ (
BOOL
)isReachableViaWiFi;
@end
Step 2: Implementation
The implementation of MTReachabilityManager
isn't too surprising. If you are unfamiliar with the singleton pattern, then the implementation of sharedManager
might seem a bit odd. Even though the MTReachabilityManager
class makes use of the singleton pattern, it is technically possible to create instances of the class. We could prevent this by checking the value of _sharedManager
in the init
, but I assume that whoever uses the MTReachabilityManager
class has taken a look at the class's interface file revealing that it adopts the singleton pattern.
#import "MTReachabilityManager.h"
#import "Reachability.h"
@implementation
MTReachabilityManager
#pragma mark -
#pragma mark Default Manager
+ (
MTReachabilityManager
*)sharedManager {
static
MTReachabilityManager
*_sharedManager =
nil
;
static
dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedManager = [[
self
alloc
]
init
];
});
return
_sharedManager;
}
#pragma mark -
#pragma mark Memory Management
- (
void
)dealloc {
// Stop Notifier
if
(_reachability) {
[_reachability
stopNotifier
];
}
}
#pragma mark -
#pragma mark Class Methods
+ (
BOOL
)isReachable {
return
[[[
MTReachabilityManager
sharedManager
]
reachability
]
isReachable
];
}
+ (
BOOL
)isUnreachable {
return
![[[
MTReachabilityManager
sharedManager
]
reachability
]
isReachable
];
}
+ (
BOOL
)isReachableViaWWAN {
return
[[[
MTReachabilityManager
sharedManager
]
reachability
]
isReachableViaWWAN
];
}
+ (
BOOL
)isReachableViaWiFi {
return
[[[
MTReachabilityManager
sharedManager
]
reachability
]
isReachableViaWiFi
];
}
#pragma mark -
#pragma mark Private Initialization
- (
id
)init {
self
= [
super
init
];
if
(
self
) {
// Initialize Reachability
self
.reachability
= [
Reachability
reachabilityWithHostname
:
@"www.google.com"
];
// Start Monitoring
[
self
.reachability
startNotifier
];
}
return
self
;
}
@end
If you decide to adopt this alternative approach and use a reachability manager that manages an instance of the Reachability
class, then don't forget to instantiate the singleton object when your application launches. You can do so by calling sharedManager
on the MTReachabilityManager
class.
- (
BOOL
)application:(
UIApplication
*)application
didFinishLaunchingWithOptions
:(
NSDictionary
*)launchOptions {
// Instantiate Shared Manager
[
MTReachabilityManager
sharedManager
];
// Initialize View Controller
self
.viewController
= [[
MTViewController
alloc
]
initWithNibName
:
@"MTViewController"
bundle
:nil
];
// Initialize Window
self
.window
= [[
UIWindow
alloc
]
initWithFrame
:[[
UIScreen
mainScreen
]
bounds
]];
// Configure Window
[
self
.window
setRootViewController
:
self
.viewController
];
[
self
.window
makeKeyAndVisible
];
return
YES
;
}
Conclusion
Notifying the user or updating the application's user interface when the network interface changes not only results in a better user experience, Apple requires that you do this if your application relies on network connectivity. It does take some effort, but the Reachability class makes it a lot easier.
- Reachability
- Reachability
- Reachability
- Reachability
- Reachability
- Reachability介绍
- Reachability源代码
- Reachability框架
- Reachability框架
- Reachability算法
- Reachability.h和Reachability.m文件
- Reachability 网络编程总结
- iOS: network reachability
- Reachability 网络编程总结
- Reachability 网络检测
- Reachability的使用
- Reachability查询联网状态
- Reachability 检查网络状态
- Singleton模式的实现方式 C#
- JAVA中使用Formatter类进行输出格式的控制
- IQKeyboardManager使用方法
- 基于Web在线考试系统的设计与实现
- 【jQuery】sele1,sele2,seleN选择器
- Reachability
- 鸟巢-一种全新的Native APP开发模式,这篇文章问您解读
- stddef.h
- Struts配置中param参数的含义
- NGUI常见问题集(待续)
- iOS HLS 流媒体文件打散问题 - 只有声音无影像
- 获得MFC窗口其它类指针的方法
- MySQL字符串连接函数
- BZOJ-1002 轮状病毒 高精度加减+Kirchhoff矩阵数定理+递推