Большинство мобильных приложений по той или иной причине получают доступ к Интернету. Это подразумевает, что эти приложения будут — или должны — вести себя по-разному, когда нет сетевого подключения. В этом кратком совете я покажу вам, как обнаруживать изменения сетевого интерфейса, используя класс Reachability Tony Million .
Решения
Несмотря на то, что Apple предоставляет образец кода для мониторинга изменений в доступности сети, класс Reachability от Apple несколько устарел и не поддерживает ARC (автоматический подсчет ссылок). Если вы используете AFNetworking , то вы можете рассмотреть AFHTTPClient
, который также позволяет отслеживать изменения сетевого интерфейса.
Тем не менее, мое предпочтительное решение — замечательный класс Reachability, созданный и поддерживаемый Tony Million . Он поддерживает ARC и использует GCD (Grand Central Dispatch). Позвольте мне показать вам, как интегрировать класс Reachability Тони.
1. Настройка проекта
Создайте новый проект в Xcode, выбрав шаблон приложения Single View Application из списка шаблонов (рисунок 1). Назовите свое приложение Reachability , введите идентификатор компании, установите iPhone для семейства устройств и установите флажок Использовать автоматический подсчет ссылок . Остальные флажки могут быть оставлены непроверенными для этого проекта (рисунок 2). Сообщите Xcode, где вы хотите сохранить проект, и нажмите « Создать» .
2. Интеграция достижимости
Шаг 1: Добавление класса достижимости
Интеграция класса Reachability Тони Миллиона тривиальна. Посетите страницу проекта GitHub , загрузите последнюю версию и перетащите Reachability.h / .m в свой проект Xcode (рисунок 3). Если вы выберете этот путь, обязательно скопируйте файлы классов в ваш проект Xcode (рисунок 4). Вы также можете использовать CocoaPods для добавления Reachability в ваш проект.
Шаг 2. Связывание с платформой конфигурации системы
Класс Reachability зависит от структуры конфигурации системы для некоторых ее функций. Выбрав свой проект в Навигаторе проектов , выберите цель « Достижимость» в списке целей, откройте вкладку « Фазы сборки » и разверните блок « Связать двоичные файлы с библиотеками» . Нажмите кнопку «плюс» и найдите SystemConfiguration.framework (рисунок 5).
3. Основы достижимости
Класс Reachability
предоставляет два способа мониторинга изменений доступности сети: блоки и уведомления. Позвольте мне показать вам, как это работает.
Шаг 1: Импорт Reachability.h
Для простоты мы добавим логику достижимости в делегат приложения. Начните с добавления оператора импорта для Reachability.h в MTAppDelegate.m, как показано ниже.
1
2
3
4
|
#import «MTAppDelegate.h»
#import «Reachability.h»
#import «MTViewController.h»
|
Шаг 2: Блоки
Сначала нам нужно создать экземпляр класса application:didFinishLaunchingWithOptions:
в application:didFinishLaunchingWithOptions:
( MTAppDelegate.m ), как показано ниже. Затем мы устанавливаем reachableBlock
и unreachableBlock
в экземпляре Reachability
. reachableBlock
вызывается, когда доступность сети меняется с недоступной на достижимую. Обратное верно для unreachableBlock
. Ключевым является отправка экземпляру startNotifier
сообщения startNotifier
чтобы он знал, что должен начать мониторинг изменений достижимости. Также важно знать, что вызов startNotifier
заставляет экземпляр startNotifier
сохранять себя, что означает, что вам не нужно хранить ссылку на объект Reachability
. Тем не менее, я не фанат этого подхода и чуть позже покажу вам альтернативное решение.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
— (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;
}
|
Прежде чем мы рассмотрим уведомления, я должен подчеркнуть, что доступные и недоступные блоки вызываются в фоновом потоке. Помните об этом, когда вам нужно обновить пользовательский интерфейс вашего приложения при изменении сетевого интерфейса.
Шаг 3: Уведомления
Преимущество использования уведомлений для изменений достижимости состоит в том, что любой объект в вашем приложении может зарегистрироваться как наблюдатель для этих уведомлений. В отличие от использования блоков, уведомления о достижимости размещаются и доставляются в основной поток. Как вы можете видеть ниже, в application:didFinishLaunchingWithOptions:
мы создаем экземпляр класса application:didFinishLaunchingWithOptions:
и сообщаем ему начать мониторинг изменений в сети.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
— (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;
}
|
Например, если контроллер представления должен быть информирован об изменениях в доступности сети, то нам нужно добавить его в качестве наблюдателя уведомлений, которые Reachability
экземпляр Reachability
. Откройте MTViewController.m
, добавьте оператор импорта для Reachability.h и обновите initWithNibName:bundle:
как показано ниже.
1
2
3
|
#import «MTViewController.h»
#import «Reachability.h»
|
01
02
03
04
05
06
07
08
09
10
|
— (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;
}
|
Каждый раз, когда изменяется сетевой интерфейс, reachabilityDidChange:
и контроллер представления может ответить соответствующим образом. Свойство object
уведомления — это экземпляр Reachability
который разместил уведомление. Класс Reachability
предоставляет ряд полезных методов экземпляра, таких как isReachable
, isReachableViaWWAN
и isReachableViaWiFi
. Вы даже можете указать экземпляру Reachability
, должен ли он считать WWAN недоступным, соответствующим образом установив свойство reachableOnWWAN
.
1
2
3
4
5
6
7
8
9
|
— (void)reachabilityDidChange:(NSNotification *)notification {
Reachability *reachability = (Reachability *)[notification object];
if ([reachability isReachable]) {
NSLog(@»Reachable»);
} else {
NSLog(@»Unreachable»);
}
}
|
4. Достижимость менеджера
Для приложений, которым требуется сетевое соединение, я обычно использую альтернативный подход для управления достижимостью. Я создаю отдельный класс с именем ReachabilityManager, который принимает шаблон синглтона. Объект singleton управляет экземпляром Reachability
и предоставляет ряд полезных методов класса. Позвольте мне провести вас через внутренности этого класса.
Шаг 1: Интерфейс
Как я уже упоминал, класс MTReachabilityManager
принимает одноэлементный шаблон и предоставляет доступ к одноэлементному объекту через sharedManager
класса sharedManager
. Это полезно, если объекту нужен прямой доступ к экземпляру reachability
которым управляет одноэлементный объект.
Посредством ряда методов класса объекты могут запрашивать у менеджера достижимости текущий сетевой интерфейс. Кроме того, объекты все еще могут добавлять себя в качестве наблюдателей для уведомлений kReachabilityChangedNotification
как мы видели ранее.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
#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
|
Шаг 2: Реализация
Реализация MTReachabilityManager
не слишком удивительна. Если вы не знакомы с одноэлементным шаблоном, то реализация sharedManager
может показаться немного странной. Хотя класс MTReachabilityManager
использует шаблон синглтона, технически возможно создать экземпляры класса. Мы могли бы предотвратить это, проверив значение _sharedManager
в init
, но я предполагаю, что тот, кто использует класс MTReachabilityManager
, взглянул на файл интерфейса класса, обнаружив, что он принимает шаблон синглтона.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
#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
|
Если вы решите принять этот альтернативный подход и использовать диспетчер достижимости, который управляет экземпляром класса Reachability
, не забудьте создать экземпляр объекта singleton при запуске приложения. Вы можете сделать это, вызвав sharedManager
MTReachabilityManager
класса MTReachabilityManager
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
— (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;
}
|
Вывод
Уведомление пользователя или обновление пользовательского интерфейса приложения при изменении сетевого интерфейса не только приводит к улучшению взаимодействия с пользователем, Apple требует, чтобы вы делали это, если ваше приложение использует сетевое подключение. Это требует определенных усилий, но класс Reachability делает это намного проще.