How to Test for Missing or Transient Capabilities in iOS Apps

By Rajiv Ramnath

To make your app reliable in iOS, the final consideration is to ensure that it deals well with missing capabilities on the device (such as the availability of specific sensors) or transient failures in these capabilities (such as access to the network).

For the former, your app checks whether a certain capability (such as the lack of a video camera) is available before it tries to do anything with that capability — for example, checking whether a certain type of sensor exists before trying to use it. The method listCapabilities in TTTSensorsController.m shows how your app can discover what is currently available.

Snippets from this method are shown here, starting with testing for the camera; also, drill down to check whether video or only still pictures are available:

  // Testing for the camera 
  BOOL cameraAvailable =
   [UIImagePickerController
    isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
  if (cameraAvailable == YES)
   [textVal appendString:@"Camera is availablen"];
  NSArray *cameraTypes =
   [UIImagePickerController availableMediaTypesForSourceType
          :UIImagePickerControllerSourceTypeCamera];
  int count = [cameraTypes count];
  for (int i = 0; i < count; i++) {
   NSString *cameraCapability = [cameraTypes objectAtIndex:i];
   if (CFStringCompare ((CFStringRef) cameraCapability,
         kUTTypeMovie,
         0))
    [textVal appendString:@"Video capability is availablen"];
   if (CFStringCompare ((CFStringRef) cameraCapability, kUTTypeImage, 0))
    [textVal appendString:@"Still capability is availablen"];
  }

Finally, here’s how you test for the availability of the audio player:

  // Testing for availability of audio
  AVAudioSession *audioSession = [AVAudioSession sharedInstance];
  if (audioSession.inputAvailable == YES)
   [textVal appendString:@"Audio input device is availablen"];
  [listOfSensorsView setText:textVal];
 }

Next, here’s how you test for the network:

  …
  // Testing for the network
  NSMutableString *textVal = [[NSMutableString alloc] init];
  NSString *networkReachability=nil;
  Reachability *reachFacade =
   [Reachability reachabilityForInternetConnection];
  NetworkStatus status = [reachFacade currentReachabilityStatus];
  if (status == NotReachable) networkReachability = @"No networkn";
  else if (status == ReachableViaWiFi)
   networkReachability = @"Wifi availablen";
  else if (status == ReachableViaWWAN)
   networkReachability = @"WAN availablen";
  [textVal appendString:networkReachability];