Refreshing iOS application or checking for connection in advance

508 views Asked by At

I'm having some issues determining what the proper application design pattern is for initially alerting users that they need to enable an internet connection.

I have an iOS app that requires an internet connection due to the wide range of data that a user could request. The app has a couple tab bar controllers within which there are navigation controllers that take users through a variety of views based on hierarchy and returned data. All requests are made asynchronously using ASIHTTPRequest using NSNotificationCenter observers that wait for a central api request class to either complete the request or report an error. In most cases a user will have downloaded at least the first requests, but I can always ask them to enable their connection in a UIAlertView and then return them to that lower level by popping other nav controller levels off of the stack if they aren't connected. Overall the application works great.

However, if a user was to first open the application with their connection disabled I am running into issues. Often my initial subviews (which are IBoutlets for ease of creating the tab-bar/navigation hierarchy) will have attempted to load before I could possibly test for the existence of a connection. I'm not sure if maybe the correct way to do this is to create a timeout in my app delegate before other things load somehow, or make an initial test request that doesn't actually retrieve any crucial data (since it seems it's nearly impossible, or at least impractical to completely re-initialize a view from scratch without being its delegate).

Does anybody have any simple method that they use to accomplish this at the application initialization stage? I feel like I must be missing something obvious since the rest of this has been so straightforward.

If someone wants me to post code I could, however I'm pretty sure this is primarily an architecture question. Also please keep in mind I would rather use observers that delegates in most cases due to the intentionally loosely coupled nature of my app.

I greatly appreciate any input on this.

3

There are 3 answers

0
Project707 On BEST ANSWER

I ended up using more notifications to do this:

I call my api request class from my app delegate with a "test request" and then listen for it in the app delegate as well. If the app delegate observes a successful response, it starts another request for which my active view controller is the observer. The object passed along contains the data the receiving controller needs to reload its view.

I think next time I need to plan my delegation a little bit better to do away with some of the notifications. However, with an application like this where the same class is used dynamically and can receive multiple sets of data or where the data can be intended for a different context, notifications do make some sense I suppose.

1
Gaurav Patel On
-(BOOL)isConnected{
BOOL connected;
const char *host = "www.google.com";
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, host);
SCNetworkReachabilityFlags flags;
connected = SCNetworkReachabilityGetFlags(reachability, &flags);
BOOL isConnected = connected && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired);
CFRelease(reachability);
return isConnected;}

this method add in app delegate.

4
FluffulousChimp On

As you suggest, it sounds like an architecture problem.

I think the timeout solution is iffy at best because the whole loading process is nondeterministic. I don't know what views you are populating with the data you are loading asynchronously; but let's say it's a UITableView for the sake of discussion. When the view first loads, there will be no data; but if a connection is available, you will asynchronously populate the table via ASIHTTPRequest callbacks.

An example:

[[CCFConnectionManager sharedManager] countScenariosForScenarioID:lwScenario.uniqueID
                                                                groupCode:groupCode
                                                        completionHandler:^(NSInteger count) {
                                                            lwScenario.completionCount = count;
                                                            dispatch_async(dispatch_get_main_queue(), ^{
                                                                [[self tableView] reloadData];
                                                            });

So in the completion handler, I update the model and send [[self tableView] reloadData]. The latter on the main thread. HTH.