在使用 RESideMenu 显示视图控制器之前,使用 AFNetworking 在 didFinishLaunching 中尽快检查可达性
Posted
技术标签:
【中文标题】在使用 RESideMenu 显示视图控制器之前,使用 AFNetworking 在 didFinishLaunching 中尽快检查可达性【英文标题】:Check reachability asap in didFinishLaunching using AFNetworking before a view controller visible with RESideMenu 【发布时间】:2014-12-26 10:10:09 【问题描述】:我在我的应用程序中使用AFNetworking,我正在通过他们的内置类检查互联网连接。这是这个的代码,
- (void) startInternetConnectivityMonitoring
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status)
switch (status)
case AFNetworkReachabilityStatusUnknown:
case AFNetworkReachabilityStatusReachableViaWWAN:
case AFNetworkReachabilityStatusReachableViaWiFi:
break;
case AFNetworkReachabilityStatusNotReachable:
break;
default:
break;
NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));
];
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
我可以通过这个函数来检查它,
- (BOOL) connected
return [AFNetworkReachabilityManager sharedManager].reachable;
我还在我的应用程序中使用RESideMenu 来设置侧边菜单,这是我的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
方法。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
[self startInternetConnectivityMonitoring];
RootViewController *rootView = [[RootViewController alloc] init];
[rootView awakeFromNib];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = rootView;
[self.window makeKeyAndVisible];
return YES;
除了 FirstViewController 之外,所有其他视图控制器都可以正常工作。在 FirstViewController 中,我正在调用网络请求,在此之前,我会检查互联网连接。这就是问题所在。每次,它都会向我显示 No internet
的 FirstViewController。因为,当它调用网络请求时,AFNetworking
不会更新互联网的状态。更新可能需要几秒钟的摩擦,但更新速度不会那么快。因为,我知道这个问题,我不想应用补丁来解决这个问题。我尝试了不同的方法来解决这个问题。用过,
sleep(2);
在从didFinishLaunchingWithOptions...
返回 YES 之前
dispatch_synq
- 冻结应用
dispatch_asynq
- 不起作用
.. and many other hacky ways
- 还没有帮助。
【问题讨论】:
【参考方案1】:不幸的是,确定连接需要一段时间,因此可能不会尽快发生。但是,您也可以注册以接收可达性通知,而不是假设您有互联网连接。在 AppDelegate didFinishLaunchingWithOptions:launchOptions 开始你的监控:
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
在您的 FirstViewController viewDidLoad 或 viewWillAppear 中,注册以接收通知:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reachabilityChanged:)
name:AFNetworkingReachabilityDidChangeNotification
object:nil];
然后在FirstViewController中添加一个方法来处理通知:
- (void)reachabilityChanged:(NSNotification *)notification
if([[AFNetworkReachabilityManager sharedManager].isReachable)
// Do web service stuff here
else
// Do non webservice stuff
如果您需要知道状态是什么,可以从通知的 userInfo 字典中获取:
- (void)reachabilityChanged:(NSNotification *)notification
NSLog(@"Rechability Changed: %@", notification.userInfo);
BOOL reachable;
NSInteger status = [[notification.userInfo objectForKey:@"AFNetworkReachabilityNotificationStatusItem"] integerValue];
switch(status)
case AFNetworkReachabilityStatusNotReachable:
NSLog(@"No Internet Connection");
reachable = NO;
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(@"WIFI");
reachable = YES;
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
NSLog(@"3G");
reachable = YES;
break;
default:
NSLog(@"Unkown network status");
reachable = NO;
break;
// do stuff with reachable
一旦 AFReachabilityManager 确定网络状态,通知就会发出,并且总是至少发出一次。
如果您只需要获取一次状态,您可以在处理通知的方法中从通知中心取消注册 FirstViewController - 从所有通知中:
[[NSNotificationCenter defaultCenter] removeObserver:self];
或针对特定通知:
[[NSNotificationCenter defaultCenter] removeObserver:self name:AFNetworkingReachabilityDidChangeNotification object:nil];
【讨论】:
【参考方案2】:我为此找到了一个简单的补丁,是的,它应该像一个魅力一样工作,而我找不到这个问题的合理解决方案。
-
我在
AppDelegate.h
BOOL isCalledOnce;
中取了一个BOOL
-
在 (
AppDelegate.m
) 中添加了如下两个方法
- (void) setAppRequestCallOnce isCalledOnce = YES;
- (BOOL) checkAppRequestCalledOnce
return isCalledOnce;
-
在可达性检查中,我做了这样的条件,
- (BOOL) connected if(![self checkAppRequestCalledOnce]) [self setAppRequestCallOnce]; return YES; return [AFNetworkReachabilityManager sharedManager].reachable;
结论:
来自FirstViewController
,当我检查可达性时,例如,
if(![delegateObj connected])
//show no internet message
这将首先调用checkAppRequestCalledOnce
方法,该方法返回一个isCalledOnce
,如果它是NO
,那么我将其设置为YES
并返回YES
(这里我们不确定可达性)。从现在开始,当我再次检查可达性时,它不会检查上述条件,而是返回实际的可达性状态。
我为什么要使用,因为即使一开始没有可用的互联网,AFNetworking
也会给我们一个错误,尽管我们可以显示它,即使我们没有实际的可达性状态。
如果您发现任何更优雅的方式,请发布或评论。
【讨论】:
【参考方案3】:我遇到了类似的问题。 AFNetworking 似乎需要一点时间才能启动。如果你想在应用程序中检查互联网连接:didFinishLaunchingWithOptions:使用:
Reachability *reach = [Reachability reachabilityForInternetConnection];
if (reach.currentReachabilityStatus != NotReachable)
//NSLog(@"internet available");
或在 AFNetworking 上设置块并等待它被调用:
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status)
if (status < ReachableViaWiFi)
// no connection
else
// connected
];
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
【讨论】:
【参考方案4】:我也遇到过同样的问题。之后,我尝试在调用 web-service 时延迟 0.3 秒,它解决了我的问题。
您可以尝试在FirstViewController
中调用网络服务之前延迟一些时间。因为AFNetworking
需要时间来监控互联网状态,并且您的控制器在AFNetworking
获得互联网状态之前加载。所以每次你都会得到AFNetworkReachabilityStatusNotReachable
。
在FirstViewController
调用 web-service 之前稍作延迟,它可能会解决您的问题。
【讨论】:
【参考方案5】:如果您检查networkReachabilityStatus
中的AFNetworkReachabilityStatusUnknown
,AFNetworking 会告诉您它尚未确定状态。因此,执行此操作的干净方法是仅在已知状态后使用reachable
状态。例如:
- (void)networkReachableWithCompletion:(CompletionBlock)_completion
if (!_completion) return; //no point continuing
if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus != AFNetworkReachabilityStatusUnknown)
_completion([NSNumber numberWithBool:[AFNetworkReachabilityManager sharedManager].reachable]);
else
[self performSelector:@selector(networkReachableWithCompletion:) withObject:_completion afterDelay:0.3];
【讨论】:
以上是关于在使用 RESideMenu 显示视图控制器之前,使用 AFNetworking 在 didFinishLaunching 中尽快检查可达性的主要内容,如果未能解决你的问题,请参考以下文章
带有 Residemenu 的 UILocalNotification
显示时更新 RESideMenu 中的 tableview 数据