Search code examples
objective-cswiftnsurlconnectioncfnetwork

CFNetwork error handling in Swift


I have a block of objective-c code that responsible for handling HTTP errors by checking the NSError code error. The code sends the error message back to a delegate (unless it's a error code that the app ignores, such as cancelled requests)

failure:^(NSURLSessionTask *task, NSError *error, id responseObject) {

   NSString *errorMessage = [self getErrorMessage:responseObject withError:error];

   if (error.code!=kCFURLErrorCancelled &&
      error.code!=kCFURLErrorCannotFindHost &&
      error.code!=kCFURLErrorCannotConnectToHost &&
      error.code!=kCFURLErrorNetworkConnectionLost &&
      error.code!=kCFURLErrorDNSLookupFailed &&
      error.code!=kCFURLErrorNotConnectedToInternet &&
      error.code!=kCFURLErrorTimedOut) {
    if ([self.delegate respondsToSelector:@selector(didFailed:)]) {
      [self.delegate didFailed:errorMessage];
    }
  }

  if (completionBlock != nil) completionBlock(NO);
}];

I have several questions / issues related to this code block.

  1. Is is sufficient to just check the error code? The framework I'm using might return a different type of errors and I'm not sure those error codes are unique.
  2. How would I go and write the same code in Swift? I did find the error codes definitions under CFNetworkErrors enum. However, the error.code & the value from the CFNetworkErrors enum cannot be compared directly, as they have different types. Is it possible to cast error.code to a CFNetworkErrors and then compare the error codes?
  3. Can I safely switch to use the NSURL errors such as NSURLErrorCancelled? Is there a 1-to-1 mapping between the CFNetworks errors and NSURL errors?

Solution

    1. It is probably not sufficient to check the error code. You almost certainly need to check the HTTP status code as well, unless the delegate method you're calling already does that. An NSError typically tells you about transport-level failures, whereas the status code tells you about server-side failures, such as a file not existing.

    2. No idea. That question is mostly unrelated to networking, so you should probably ask a separate question for it, and tag it as a Swift question. :-)

    3. Yes, you should be using the Foundation codes. The values should always be identical, but there are likely to be more Foundation error codes than CF codes going forward, as not all of the Foundation-level functionality is exposed publicly at the CF layer.