ПРОГРАММИРОВАНИЕ ПОД IPHONE, IPAD OBJECTIVE-C часть 2

14. Работа с сетью

Проверка соединения с Internet

Нет смысла описывать полезность функции проверки соединено устройство с сетью Интернет или нет. Важно это делать правильно. Я видел, когда люди для проверки скачивают страничку google.com. Если страничка закачалась — значит есть соединение. Но это не главный недостаток, это происходило с блокировкой интерфейса. То есть закачка странички через сеть мобильного оператора длилась 1-2 минуты. В этой статье я пишу как правильно делать такую проверку.

 

Сначала создадим проект на основе представления Single View Application и назовем его MyReachability. Такое имя я выбрал не просто так. В этом проекте мы будем использовать класс написанный сотрудниками компании Apple, а называется он Reachability. Скачать его можно по этой ссылке. Распакуйте содержимое архива и добавьте в проект. Этот класс использует фреймверк SystemConfiguration. Добавьте его в проект (если забыли как это делать — можете воспользоваться этим примером). Следует учесть, что класс Reachability не поддерживает автоматический подсчет ссылок, а значит, вам нужно добавить флаг компилятора -fno-objc-arc. О том как это сделать можете прочитать в уроке Automatic Reference Counting (ARC).

 

В этот раз нам прийдется вносить изменения в класс AppDelegate. Этот класс имеет полезное свойство, экземпляр этого класса всегда существует в программе и всегда один. Такой класс называется синглтоном более подробно о таких классах можете прочитать в уроке Синглтон (Singleton). Сейчас нам следует внести изменения в интерфейс класса AppDelegate:

 

AppDelegate.h

<code data-result="[object Object]">#import &lt;UIKit/UIKit.h&gt;
#import "Reachability.h"

@class ViewController;

@interface AppDelegate : UIResponder &lt;UIApplicationDelegate&gt;

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) ViewController *viewController;

@property (assign, nonatomic) NetworkStatus netStatus;
@property (strong, nonatomic) Reachability  *hostReach;

- (void)updateInterfaceWithReachability: (Reachability*) curReach;

@end</code>

 

Здесь я добавил два свойсва, в netStatus будет храниться состояние интернет-соединения, а hostReach — экземпляр класса, который следит за изменениями состояния сети. Метод updateInterfaceWithReachability: будет вызываться каждый раз при изменении состояния сети и менять значение свойства netStatus.

 

Соответственно изменим реализацию этого класса AppDelegate:

 

AppDelegate.m

<code data-result="[object Object]">#import "AppDelegate.h"
#import "ViewController.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize viewController = _viewController;
@synthesize netStatus;
@synthesize hostReach;

- (BOOL)application:(UIApplication *)application 
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(reachabilityChanged:) 
                                                 name:kReachabilityChangedNotification 
                                               object:nil];
    self.hostReach = [Reachability reachabilityWithHostName:@"www.apple.com"];
    [hostReach startNotifier];
    [self updateInterfaceWithReachability: hostReach];

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void) updateInterfaceWithReachability: (Reachability*) curReach {
    self.netStatus = [curReach currentReachabilityStatus];
}

- (void) reachabilityChanged: (NSNotification* )note {
    Reachability* curReach = [note object];
    NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
    [self updateInterfaceWithReachability: curReach];
}</code>

 

На страничку я добавил только ту часть кода, в которая подверглась изменениям.
Этих незначительных изменений достаточно чтобы наша программа узнавала подключено устройство к сети или нет. Все, что нам осталось сделать — это вывести информацию о подключении на экран. Для этого изменим интерфейс класса ViewController:

 

ViewController.h

<code data-result="[object Object]">#import &lt;UIKit/UIKit.h&gt;

@interface ViewController : UIViewController

@property (nonatomic, retain) IBOutlet UILabel *resultTest;

- (IBAction)testNet;

@end</code>

 

Как видно с кода, внесенные изменения связаны с интерфейсом. Откройте файл ViewController.xib и добавьте на него кнопку с текстовым полем. Затем свяжите обект resultTest с текстовым полем, а метод testNet с действием нажатия на кнопку. Если кто-то не помнит как это делать — можно посмотреть здесь.

Осталось изменить реализацию класса ViewController:

 

ViewController.m

<code data-result="[object Object]">#import "ViewController.h"
#import "AppDelegate.h"

@implementation ViewController

@synthesize resultTest;

- (void)viewDidUnload
{
    [super viewDidUnload];
    self.resultTest = nil;
}

- (IBAction)testNet {
    AppDelegate * appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];

    NSString *resultValue = nil;
    if (appDelegate.netStatus == NotReachable) {
        resultValue = @"Not Connection";
    } else if (appDelegate.netStatus == ReachableViaWiFi) {
        resultValue = @"Connection ReachableViaWiFi";
    } else if (appDelegate.netStatus == ReachableViaWWAN) {
        resultValue = @"Connection ReachableViaWWAN";
    }

    resultTest.text = resultValue;
}

@end</code>

 

Самым непонятным в этом коде может быть первая строка в методе testNet. С помощью этой строки мы получаем ссылку на тот единственный экземпляр класса о котором я писал в начале статьи (но чтобы это работало не забудьте импортировать нитерфейс этого класса). После чего следует проверка на возможные значения свойства netStatus и формирование результата на основании этих значений.


Следует учесть тот факт, что программа сама отслеживает изменения состояния сети. Если по какой-то причине на устройстве пропало соединение — вам не нужно перезапускать программу чтобы это узнать. Значение переменной netStatus изменяется само, а при очередном нажатии на кнопку Test NET вы увидите результат.

Как видите, проверять наличие соединения в iOS очень просто и не стоит для этого изобретать велосипед или, какие-то подпорки.