Wednesday, February 18, 2015

New NSError Pattern Support in iOS and OS X Clients

Remember our blog post about developing iOS apps with Swift and Lightstreamer? It was 7 months ago, Swift had been introduced by Apple only a few weeks before, and object-oriented programming fans (like me) were wondering why there was no support for structured exception handling.

Our iOS and OS X client libraries used to rely on exceptions. Both to maintain an interface reasonably similar to other client libraries (Java/Android, mainly), and to use a well-established pattern for error handling.

Now, seven months have passed and there are still no traces of exception handling in Swift. Not even in the just-announced version 1.2 of the language. So, with version 1.4 of the iOS client library, and version 1.2 of the OS X, we have introduced an alternative signature for exception-throwing methods that supports the common NSError pattern of Cocoa and Cocoa Touch. To the benefit of developers using Swift and of all the developers out there that simply don't like exceptions (and there are many).

New NSError-Returning Methods

Consider these 3 methods, as an example:

They can all throw an exception for a number of reasons:
  • openConnectionWithInfo if the connection process is interrupted;
  • subscribeTableWithExtendedInfo if the tableInfo requests a data adapter that is not available on the server;
  • sendMessage if the client is not connected;
  • and so on.
New versions of these methods are as follows:

These methods simply wrap previous methods with a @try-@catch clause and, if thrown, wrap runtime exceptions in an NSError object structured in this way:
  • the error domain is "LSLightstreamerErrorDomain";
  • the error code is the server error code,when the exception caught is of LSPushServerException class, 0 otherwise;
  • the userInfo reports the exception name as the localized description (NSLocalizedDescriptionKey) and the exception reason as the failure reason (NSLocalizedFailureReasonErrorKey).
For example, calling subscribeTableWithExtendedInfo with the wrong data adapter will result in an NSError filled as follows:
  • domain: "LSLightstreamerErrorDomain"
  • code: 17
  • userInfo:
    • NSLocalizedDescription: "Lightstreamer server exception"
    • NSLocalizedFailureReason: "Server exception (reason: 'Lightstreamer error received: 17 Requested Data Adapter, XYZ, not found')"
The exception/failure reason is designed to be a human-readable explanation of the problem.

Important note: following the pattern suggested by Apple, there are still cases where an exception is thrown, even when using new methods. In particular, exceptions of LSPushClientException class are not caught by the @try-@catch wrap and reach the user code. These exceptions are thrown typically when a programmer error occurs, such as when conflicting parameters are specified or mandatory parameters are missing.

Using New Methods With Swift

Using new NSError-returning methods with Swift is easy, just prepare your NSError object as you would do with any other API, and call the method:

Our Swift Chat example has been updated to use new methods. Take a look to see their use in a complete app.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.