Dec 14

Protocols to Closures in Swift

After releasing Socivy in a very short time, it required some refactoring in the API level. Since MVC pattern is in the foundation of the iOS development, without touching UI components, I can directly refactor only API part of the project.

Well, I highly used protocols in my implementation. For instance, if user makes a request to get available routes in the system, it uses already constructed SocivyAvailableRouteAPI to make fetch routes from the API. It handles the requests asynchronously and returns the response by calling delegate function like routeRequestDidFinish(), this is enormously helpful for me to separate controllers and models however, after increases in our API methods, unfortunately it increased protocols and unnecessary repetitions.

Not only this, increased a spaghetti code, it also affected the compile time. A big advantage was that everything was explicit, and implementation was pretty fast, it helped  our tight development schedule.

I will be adding a chatting feature for Socivy for the end of the semester for CS392 course. Before starting the feature, I thought it would be better to refactor the code and use closures and Factory and a kind of Facade pattern to reduce redundancy and decrease number of classes.

Because of the architecture of SocivyAPI security, it requires re-logins sometimes. Whenever an API request fails due to expired session, it should automatically restore and continue the calling the action and trigger the callback to update the user interface. I subclassed NSURLConnection, added completionHandler and errorHandler:

  • completionHandler: (response:NSMutableData->())?
  • errorHandler: (error:NSError->())?

Basically if request returns successfully or with an error, it will be handled by these handlers. Another problem was the data validation, NSMutableData must be a convertible to a valid JSON object. For that, I implemented a Model layer that gets exactly same handlers but this time completionHandler gets JSON as parameter. In that layer, I also handled session expires, it automatically re-logins after the validation, so no need for extra care for all methods that require authentication.

However, delegates must be removed after these, since the protocols are removed. For instance:

It is currently on ViewController side:

With closures, I think it is much cleaner than delegates, you can handle different cases, much better than delegates. On the other hand, you should never do this:

This is not very expressive, and would eventually lead to a callback hell.