调用 Reachability startNotifier 后,Network 状态变为 0

Posted

技术标签:

【中文标题】调用 Reachability startNotifier 后,Network 状态变为 0【英文标题】:After calling Reachability startNotifier, the Network status changes to 0 【发布时间】:2013-02-13 09:39:53 【问题描述】:

在我的 ios 应用程序中,我需要使用 Reachability 来完成以下任务:

    在渲染视图控制器时,应用程序需要检查连接状态,并相应地显示连接图标图像(在线或离线)。 当用户停留在视图控制器上时,如果互联网连接状态发生变化,将通知应用程序发生变化,然后相应地执行一些任务。

我在我的应用程序中使用了由 Tony Million 生成的 Reachability 类,但是发生了一件奇怪的事情: 调用startNotified方法后,可达状态变为0(NotReachable)

以下是我的代码:

BTLandingViewController.h

#import <UIKit/UIKit.h>
#import "MBProgressHUD.h"
#import "Reachability.h"

@interface BTLandingViewController : UIViewController <UIAlertViewDelegate>

    __weak IBOutlet UIImageView *internetIndicator;

    MBProgressHUD *hud;
    Reachability *reach;

    UIAlertView *emptyRecordsAlert;
    UIAlertView *syncReminderAlert;


@end

部分代码在 BTLandingViewController.m

#import "BTLandingViewController.h"

@interface BTLandingViewController ()
@end
@implementation BTLandingViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) 
        // Initialize reachability
        reach = [Reachability reachabilityWithHostname:BTReachTestURL];
    
    return self;


- (void)viewDidAppear:(BOOL)animated

    [super viewDidAppear:animated];

    // Register with reachability changed notification
    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(reachabilityChanged:)
                                             name:kReachabilityChangedNotification
                                           object:nil];

    NetworkStatus internetStatus = [reach currentReachabilityStatus]; // value = 1 or 2

    ***// PS: If there is connection, before [reach startNotifier], the internetStatus's   value reflects the connection status (1 or 2)***

    // Start notify reachability change
    [reach startNotifier];

    internetStatus = [reach currentReachabilityStatus]; // Value = 0;

    ***// PS: Even if there is connection, after [reach startNotifier], the internetStatus's value becomes 0***

感谢您的帮助。

【问题讨论】:

你有没有关注苹果提供的可达性示例 已在代码中编辑您的帖子,必须先设置通知中心,然后再设置通知中心 您在项目中使用 ARC 吗?如果没有,我猜你必须保留 Reachability 对象。我在很多项目中都使用了 Reachability,但从来没有遇到过这样的问题。而且,是的,正如@Vinodh 建议的那样,您必须在启动通知程序之前注册通知。祝你好运! 谢谢大家,但问题仍然存在。我正在使用由 Tony Million 创建的 ARC 兼容版本的可达性。在通知中心注册后,我已经更改了启动通知程序。请检查我的代码。但是即使有互联网连接,调用 startNotifier 后网络状态仍然会变为 0。 【参考方案1】:

我终于通过解决上面提到的 startNotifier 陷阱解决了这个问题。调用 startNotifier 确实将网络状态更改为 0,但我声明了一个变量来存储视图控制器呈现时的初始网络状态。然后在处理由reachabilityChanged通知触发的动作的方法中的if语句中使用变量的值。以下是我的代码:

BTLandingViewController.h

#import <UIKit/UIKit.h>
#import "MBProgressHUD.h"
#import "Reachability.h"

@interface BTLandingViewController : UIViewController <UIAlertViewDelegate>

    __weak IBOutlet UIImageView *internetIndicator;

    MBProgressHUD *hud;
    NSInteger initialNetworkStatus;

    UIAlertView *emptyRecordsAlert;
    UIAlertView *syncReminderAlert;  


@end

BTLandingViewController.m

#import "BTLandingViewController.h"
#import "BTSyncEngine.h"
#import "BTInstructorLoginViewController.h"
#import "BTGlobalParams.h"

@interface BTLandingViewController ()

@end

@implementation BTLandingViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) 

    
    return self;


- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.


- (void)didReceiveMemoryWarning

    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


- (void)viewDidUnload 
    internetIndicator = nil;
    [super viewDidUnload];


- (void)viewDidAppear:(BOOL)animated

    [super viewDidAppear:animated];

    // Register with sync complete notification
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(syncCompleted:) name:@"BTSyncEngineSyncCompleted" object:nil];

    // Register with reachability changed notification
    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(reachabilityChanged:)
                                             name:kReachabilityChangedNotification
                                           object:nil];

    Reachability *reach = [Reachability reachabilityWithHostname:BTReachTestURL];

    reach.reachableBlock = ^(Reachability * reachability)
        dispatch_async(dispatch_get_main_queue(), ^
            initialNetworkStatus = 1;

            [internetIndicator setImage:[UIImage imageNamed:@"online_indicator.png"]];

            // Start syncing local records with the remote server
            [[BTSyncEngine sharedEngine] startSync];
            hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
            hud.labelText = @"Sync in progress";
        );
    ;

    reach.unreachableBlock = ^(Reachability * reachability)
    
        dispatch_async(dispatch_get_main_queue(), ^
            initialNetworkStatus = 0;

            [internetIndicator setImage:[UIImage imageNamed:@"offline_indicator.png"]];

            // If the initial sync has been executed
            // then use the cached records on the device
            if ([[BTSyncEngine sharedEngine] initialSyncComplete]) 
                // Go to instructor login screen
                BTInstructorLoginViewController *instructorLoginViewController = [[BTInstructorLoginViewController alloc] init];
                [instructorLoginViewController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
                [self presentViewController:instructorLoginViewController animated:YES completion:nil];
            
            // If the initial sync has not been executed
            // show an alert view
            else 
                emptyRecordsAlert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"Please connect to the internet to load data for the first time use." delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
                [emptyRecordsAlert show];
            

        );
    ;

    [reach startNotifier];



- (void)viewDidDisappear:(BOOL)animated

    [super viewDidDisappear:animated];

    // Unregister with reachability changed notification
    [[NSNotificationCenter defaultCenter] removeObserver:self name:kReachabilityChangedNotification object:nil];

    // Unregister with sync complete notification
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"BTSyncEngineSyncCompleted" object:nil];


- (void)syncCompleted:(NSNotification *)note

    // Update the global sync completed flag
    [[BTGlobalParams sharedParams] setSyncCompleted:YES];

    // Hide syncing indicator
    [MBProgressHUD hideHUDForView:self.view animated:YES];

    // Go to instructor login screen
    BTInstructorLoginViewController *instructorLoginViewController = [[BTInstructorLoginViewController alloc] init];
    [instructorLoginViewController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
    [self presentViewController:instructorLoginViewController animated:YES completion:nil];


- (void)reachabilityChanged:(NSNotification *)note

    Reachability *reach = [note object];

    if ([reach isReachable] && !initialNetworkStatus) 

        [internetIndicator setImage:[UIImage imageNamed:@"online_indicator.png"]];

        // Start syncing local records with the remote server
        [[BTSyncEngine sharedEngine] startSync];
        hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
        hud.labelText = @"Sync in progress";

    


@end

【讨论】:

以上是关于调用 Reachability startNotifier 后,Network 状态变为 0的主要内容,如果未能解决你的问题,请参考以下文章

使用Reachability实时监测网络连通性

iOS:Reachability网络监听

Reachability的使用

Network Link Conditioner 不能与 Reachability 一起使用?

iOS开发实践之网络检测Reachability

iOS开发实践之网络检測Reachability