Пытаетесь правильно отобразить предупреждение об ошибке сети в приложении iPhone? - PullRequest
2 голосов
/ 27 января 2011

Хорошо, поэтому я пытаюсь заставить это приложение показывать коды предупреждений об ошибках сети. Я добавил инфраструктуру SystemConfiguration.framework и пример кода Apple «Reachability».

Вот файл viewcontroller.h:

#import <UIKit/UIKit.h>

@class Reachability;

@interface Test_Internet_ConnectionViewController : UIViewController {

    Reachability* internetReachable;
    Reachability* hostReachable;
}

@property BOOL internetActive;
@property BOOL hostActive;

- (void) checkNetworkStatus:(NSNotification *)notice;

@end

Вот файл viewcontroller.m:

#import "Test_Internet_ConnectionViewController.h"
#import "Reachability.h";

@implementation Test_Internet_ConnectionViewController

@synthesize internetActive;
@synthesize hostActive;

/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}
*/

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

        // check for internet connection
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];

        internetReachable = [[Reachability reachabilityForInternetConnection] retain];
        [internetReachable startNotifier];

        // check if a pathway to a random host exists
        hostReachable = [[Reachability reachabilityWithHostName: @"www.apple.com"] retain];
        [hostReachable startNotifier];

        // now patiently wait for the notification
    }

/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void) checkNetworkStatus:(NSNotification *)notice
{
    // called after network status changes

    NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
    switch (internetStatus)

    {
        case NotReachable:
        {
            NSLog(@"The internet is down.");
            self.internetActive = NO;

            UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:@"Internet Unavailable" message:@"This page cannot load, please check your internet connection and try again." delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
            [errorView show];
            [errorView release];

            break;

        }
        case ReachableViaWiFi:
        {
            NSLog(@"The internet is working via WIFI.");
            self.internetActive = YES;

            break;

        }
        case ReachableViaWWAN:
        {
            NSLog(@"The internet is working via WWAN.");
            self.internetActive = YES;

            break;

        }
    }

    NetworkStatus hostStatus = [hostReachable currentReachabilityStatus];
    switch (hostStatus)

    {
        case NotReachable:
        {
            NSLog(@"A gateway to the host server is down.");
            self.hostActive = NO;

            break;

        }
        case ReachableViaWiFi:
        {
            NSLog(@"A gateway to the host server is working via WIFI.");
            self.hostActive = YES;

            break;

        }
        case ReachableViaWWAN:
        {
            NSLog(@"A gateway to the host server is working via WWAN.");
            self.hostActive = YES;

            break;

        }
    }
}

- (void)dealloc {
    [super dealloc];

        [[NSNotificationCenter defaultCenter] removeObserver:self];

    }

@end

Если при открытии приложения нет интернета, ошибка работает, как предполагалось, но если приложение теряет соединение после того, как оно изначально открылось с интернет-соединением, ошибка отображается 3 раза, когда я, очевидно, хочу, чтобы она отображалась только один раз.

Я думаю, что это может быть что-то в классе Reachability, где оно отправляет уведомление 3 раза, возможно, в 3 разных местах. Я не знаю, почему это происходит, но я думаю, что решение может заключаться в том, чтобы удалить два вызова, которые я не хочу, из класса Reachability, но я не знаю, как.

Может кто-нибудь помочь мне, пожалуйста? Заранее спасибо.

EDIT:

8 предупреждений и 4 ошибки:

«TestViewController» может не отвечать на «+ checkConnectivity»

Инициализация делает целое число из указателя без приведения

Локальное объявление «связности» скрывает переменную экземпляра

«MyReachability» необъявлено

необъявленная досягаемость

'TestViewController' может не отвечать на '-siteAvailable'

'TestViewController' может не отвечать на '-addConnectivityView'

Переопределение '- [достижимость TestViewControllerChanged:]'

«MyReachability» необъявлено

TestViewController может не отвечать на '-siteAvailable'

TestViewController может не отвечать на '-addConnectivityView'

TestViewController может не отвечать на '-removeConnectivityView'

Ответы [ 2 ]

2 голосов
/ 28 января 2011

Да, по какой-то причине он отправляет уведомления несколько раз.Чтобы преодолеть это, я сохранил переменную состояния сети в делегате приложения, который был наблюдателем для kReachabilityChangedNotification.Представление было наблюдателем для пользовательского kViewReachabilityChangedNotification, которое было отправлено делегатом приложения, когда значение действительно изменилось.Более того, после получения уведомления о доступности я вызвал функцию Reachability для получения текущего состояния сети и соответственно изменил переменную делегата приложения.Тогда я мог бы послать уведомление представлению, чтобы обновить себя.

Этот обходной путь уродлив, но работает.Я потратил много времени на то, чтобы понять, почему уведомления отправляются таким образом, и, наконец, отказался от поиска этого решения.

РЕДАКТИРОВАТЬ: Вот ваш пример - у меня все еще нет подходящего места для размещения всех рабочих примеров, поэтому, пожалуйста,попытаться выяснить решение на примере кода: доступность подкласса:

@ interface MyReachability: доступность {} + (BOOL) connectedToNetwork;@ end

@ реализация MyReachability

+ (BOOL) connectedToNetwork {
    // Create zero addy
    struct sockaddr_in zeroAddress;
    bzero(&zeroAddress, sizeof(zeroAddress));
    zeroAddress.sin_len = sizeof(zeroAddress);
    zeroAddress.sin_family = AF_INET;

    // Recover reachability flags
    SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
    SCNetworkReachabilityFlags flags;

    BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
    CFRelease(defaultRouteReachability);

    if (!didRetrieveFlags)
    {
        return NO;
    }

    BOOL isReachable = flags & kSCNetworkFlagsReachable;
    BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
    if (needsConnection && (flags & kSCNetworkReachabilityFlagsIsWWAN)) {
        needsConnection = NO;
    }
    return (isReachable && !needsConnection) ? YES : NO;
}

@ end In YourApplicationDelegate.h:

@interface YourApplicationDelegate :NSObject
{
     BOOL connectivity;
}
- (void) reachabilityChanged:(NSNotification *) note;
- (BOOL) checkConnectivity;
@end

В YourApplicationDelegate.m добавьте функцию initReachability, чтобы вызвать ее для инициирования уведомлений отКласс достижимости.

- (void) initReachability
{
    MyReachability * reachability = [ MyReachability sharedReachability ];

    //[ reachability setHostName: [self hostName] ];
    [ reachability setNetworkStatusNotificationsEnabled: YES ];

    [self siteAvailable];

    NSNotificationCenter * notificationCenter = [ NSNotificationCenter defaultCenter ];
    [ notificationCenter addObserver: self
                            selector: @selector( reachabilityChanged: )
                                name: @"kNetworkReachabilityChangedNotification"
                              object: nil ];

    connectivity = [MyReachability testConnection:NO];
    if (!connectivity) {
        if (![MyReachability testConnection:NO]) {
            [self addConnectivityView];
        }
    }
}


- (BOOL) checkConnectivity
{
    return connectivity;
}

- (void) reachabilityChanged:(NSNotification *) note
{
    BOOL    newConnectivity = [MyReachability testConnection:NO];
    if (connectivity != newConnectivity) {
        connectivity = newConnectivity;
        [self siteAvailable];
        if (![MyReachability testConnection:NO]) {
            [self addConnectivityView];
        } else {
            [self removeConnectivityView];
            connectivity = YES;
            [[NSNotificationCenter defaultCenter] postNotificationName:@"kAppNetworkReachabilityChangedNotification" object:nil];
        }
    }
}

Обратите внимание, что @ "kAppNetworkReachabilityChangedNotification" - это пользовательское уведомление, на которое ваше представление должно подписаться.

В функции viewDidLoad контроллера вашего представления:

-(void) viewDidLoad
{
       // your customization
    NSNotificationCenter * notificationCenter = [ NSNotificationCenter defaultCenter ];
    [ notificationCenter addObserver: self
                            selector: @selector( reachabilityChanged: )
                                name: @"kAppNetworkReachabilityChangedNotification"
                              object: nil ];

}


- (void) reachabilityChanged: (NSNotification *) note
{
    BOOL connectivity = [YourAppDelegate checkConnectivity];

    if (connectivity) {
           // update your view accordingly
    } 

}
0 голосов
/ 25 января 2012
[[NSNotificationCenter defaultCenter] addObserver:self 
                           selector:@selector(handleNetworkChange:) 
                           name:kReachabilityChangedNotification object:nil];

Приведенную выше строку кода следует вызывать только один раз для всего приложения.Если вы вызываете эту строку кода в функции, которая вызывается много раз, уведомление также показывает много предупреждений.Поэтому я рекомендую вам создать одноэлементный класс, который будет жить во всем приложении и вызывать указанную выше строку кода в области, где создается объект для одноэлементного класса.

Примечание: указанную выше строку кода следует вызывать толькоодин раз для всего приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...