Supporting Online and Offline - iOS

Now that the concrete classes have been written, it's time to provide the user with functionality to swap between being online and offline.

I've added a new event in the EventManager.h file: #define EM_TOGGLE_OFFLINE 140

I've updated the TopViewController class to add an additional menu item:

  1. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
  2. {
  3. self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  4. if (self) {
  5. menuIsVisible = NO;
  6. menuEntries = [[NSMutableArray alloc] init];
  7. MenuEntry *me = [[MenuEntry alloc] initWithText:@"Locations (Map)" andIcon:nil
  8. andMessage:EM_NAV_LOCAL_SPOTS_MAP];
  9. [menuEntries addObject:me];
  10. me = [[MenuEntry alloc] initWithText:@"Locations (List)" andIcon:nil
  11. andMessage:EM_NAV_LOCAL_SPOTS_LIST];
  12. [menuEntries addObject:me];
  13. me = [[MenuEntry alloc] initWithText:@"Capture a Catch" andIcon:nil
  14. andMessage:EM_NAV_CAPTURE_CATCH];
  15. [menuEntries addObject:me];
  16. me = [[MenuEntry alloc] initWithText:@"Recent Catches" andIcon:nil
  17. andMessage:EM_NAV_LIST_CATCHES];
  18. [menuEntries addObject:me];
  19. me = [[MenuEntry alloc] initWithText:@"Go Offline" andIcon:nil
  20. andMessage:EM_TOGGLE_OFFLINE];
  21. [menuEntries addObject:me];
  22. toggleOnlineEntry = me;
  23. toggleIndex = 4;
  24.  
  25. me = [[MenuEntry alloc] initWithText:@"Log Out" andIcon:@"ic_drawer.png"
  26. andMessage:EM_USER_LOGOUT];
  27. [menuEntries addObject:me];
  28.  
  29. }
  30. return self;
  31. }

And I've updated the menuItemClicked: method to toggle the menu item text based on the previous value.

  1. -(void) menuItemClicked: (int) identifier {
  2. [self toggleMenu];
  3. [eventManager handleEvent:identifier withData:nil];
  4. if (identifier == EM_TOGGLE_OFFLINE) {
  5. if ([toggleOnlineEntry.text isEqualToString:@"Go Offline"]) {
  6. toggleOnlineEntry.text = @"Go Online";
  7. } else {
  8. toggleOnlineEntry.text = @"Go Offline";
  9. }
  10. }
  11. [menuVC updateEntry:toggleOnlineEntry atIndex:toggleIndex];
  12. }

In AppDelegate.m I've added code to the handleEvent: method to react to the event:

  1. /*
  2.  * Implementation of the EventManager protocol. The method helps navigate between the various
  3.  * view controllers. This should probably be migrated to it's own class, because it's
  4.  * getting quite large in size.
  5.  */
  6. -(void) handleEvent: (int) eventID withData: (id) data {
  7. switch (eventID) {
  8.  
  9. // ...
  10.  
  11. case EM_TOGGLE_OFFLINE:
  12. [ServiceFactory setOnline:!([ServiceFactory isOnline])];
  13. break;
  14.  
  15. // ...
  16. }
  17. }

And lastly, I've updated the ServiceFactory to return different classes based on the online / offline mode:

  1. +(id<LocationService>) getLocationService {
  2. id<EventManager> em = (id<EventManager>)[[UIApplication sharedApplication] delegate];
  3. if (_online) {
  4. LocationServiceWeb *lsw = [[LocationServiceWeb alloc] init];
  5. [lsw setUserId:[em getUserId]];
  6. [lsw setToken:[em getToken]];
  7. return lsw;
  8. } else {
  9. LocationServiceDB *lsdb = [[LocationServiceDB alloc] init];
  10. [lsdb setUserId:[em getUserId]];
  11. return lsdb;
  12. }
  13. }

There are no additional changes to make to the application; the new persistence framework makes all of the alterations transparent to the remaining code.

When the application is launched, it's initially in online mode. Displaying locations shows the following:

To go offline, select "Go Offline" from the menu:

Now, displaying locations shows the following:

This completes the iOS implementation of offline mode. Now, I'll show the same code for Android.