Apple provides many tools for implementing concurrency in your application.
NSOperationQueue, GCD, or simply using
performSelectorInBackground:withObject: that is available on each and every object, are just some examples. The tools are there, yet implementing good concurrency is hard.
The solution I have found is not yet another tool, or framework, but a simple pattern. I have not found an existing name for the pattern so I call it Sync-Async Pair. The idea is to hide the complexity of asynchronous calls and call-back behind a facade, and have a straightforward synchronous implementation. An implementation that is easy to write, test and extend.
As the name suggests the pattern consist of a method pair, one is synchronous, and the other is asynchronous. The asynchronous method is backed by the synchronous implementation, and is only responsible for erecting a simplified facade in front of the sometimes complex concurrent implementation.
The first priority is to expose a clean API, the second priority is an implementation that is simple, testable and maintainable. Turns out that beginning with a clean API design (how to use the code), steers you towards a clean implementation (how to write the code). Most developers do the mistake to first write the code, and then struggle to try to use their own code.
Sync-Asyn Pair begins by defining a public API that then steers towards a clean implementation. Let’s assume we are implementing some kind of a book reader. We need two model objects;
CWChapter. Both books and chapters are fetched from the network, so we need concurrency in order to not block the UI thread.
For this example let’s focus only on fetching the chapters associated with a book. All other operations would be implemented in a similar fashion. First we need a public API, two methods for the sync-async pair on
CWBook, and a delegate protocol.
@protocol CWBookFetchChaptersDelegate <NSObject>
The synchronous method
fetchChaptersWithError: is very straightforward to implement.
NSURL* url = [self URLForFetchingChapters];
NSData* data <