One of the most appreciated features by iPad users is the possibility to read books, magazines and newspapers. Practically all major publishers are in the App Store with apps dedicated to their products but there also many other minor publishers, in every country, that entered in the iOS world with one or more apps.
Today a publisher that wants to enter in the App Store with his own magazine has several decisions he needs to make. Some of these are:
- is it better to publish a specific app for the magazine or use a newsstand app as Zinio?
- in case we decide to use our own app, should we contact an iOS dev to have a tailored product or use a web-based service that provides us in short time with a standard app?
- should the magazine service be hosted by a third party or by the publisher itself?
- is it better to re-use existing PDF or make a completely new digital magazine (e.g. if you use the Adobe Digital Publishing suite)?
Of course all these decisions will have impact on development costs, web services hosting and maintenance and finally the magazine design flow.
The author of this post has gained some experience by developing and releasing on the App Store several magazines.This series of articles is based on the experience acquired by developing some custom magazine apps and will try to depict what is the architecture of an iPad magazine app starting from the building blocks and entering into the coding challenges occurring on these blocks. We hope that any developer that should have the chance to build an iPad app can take some benefit reading these articles.
Part 1 – Architecture
The scheme below shows the three main screens of a typical magazine app.
note:Even if we’ll mainly refer the iPad device, all considerations can be applied to the iPhone too.
The first screen is the Store screen. This is typically the first view presented to the user (with the exception of the splash screen if required by the publisher) and provides the user the list of all issues that are currently available for purchase (with the term “purchase” we also mean “free” issues, which obviously are zero-priced).
note:In a typical magazine app we have only one kind of magazine, so the choice will be restricted to the last available issue and a set of older issues.
Of course for a more complex app, e.g. a book seller or multi-magazine app, this screen could be more complex as in such case products are organized by categories and then we could have a hierarchical representation of the same screen. Typically issues are represented with their cover and these covers are shown as a grid, or as a scrolling stand or using the well-know “coverflow” effect.
Together with the cover each issue is classified by its name, its release date and of course the price represented in the user currency. Besides a set of actions are associated to each issue, typically: purchase, download, preview.
Once an issue has been purchased, it should be automatically transferred to the Library view. This screen (which is usually accessible using the tab bar at the bottom) will show the list of issues that have been purchased. From this view the user can, for each issue, decide to read, delete, archive or download it.
Finally the Reader is the part of the app that allows the user to view the magazine: it can be a general purpose PDF or e-pub reader, or use (but this is not recommended as the capabilities are quite limited) the system Preview feature or finally be a custom reader: this depends on the format the issues are downloaded by the app.
Some publishers may ask to merge the Store and Library sections: this is a natural choice for those magazines which have a monthly (or lower) periodicity: in such case – due to the low number of issues available – it could be easier to show all covers in the same screen providing to the user different actions according to the fact that the magazine has been purchased or not.
A magazine app with the right architecture should be able to decouple the visual structure from the functional blocks. The reason for this is that both the publisher and the UI designer could come out with completely new ideas on how to represent the store on the screen, and it would be a nightmare for the developer to integrate each time his own back-end code with the specific needs of the new user interface. So to guarantee the maximum re-usability of the Store Manager and modeling structure it is good idea to architect the app following the MVC (Model View Controller) pattern as recommended by Apple for Cocoa apps.
Below you can see a high level functional blocks diagram.
The Publisher Server cloud symbol in the diagram represents all internet services, which are not part of the app. Normally this includes the server infrastructure used as storage for the magazines and the set of web services that will provide the magazine information to be seen on the store. This back-end can be hosted on the customer owned servers, or on specific sites such as Amazon S3 or finally on the developer server (but in such case be careful to provide a sufficient bandwidth and minimum downtime).
The Store Manager block is the central functional piece of the app. Its role is to communicate with the back-end server(s) and dispatch acquired data to the other parts of the app.
Initially the Store Manager needs to fetch from the back-end service the list of all available issues. How this can be done is specific of the implementation. We can use a simple XML or JSON file in case the list of issues is not huge, or we can establish a more complex protocol in case the publisher catalog is too large to be downloaded each time. E.g. we may provide access to several magazines which are organized by category or implement a search feature.
noteThe communication between the server and the app is one-way as data is transferred from the server to the app while the opposite flow could be limited to a minimum data exchange consisting of purchase transactions, simple http queries or analytics on the app usage.
From the point of view of the developer it makes sense to insert an intermediate communication layer (not shown in the diagram) between the server and the Store Manager: the advantage for this is that the Store Manager will expose a set of simple and general purpose APIs and at the same time the communication layer will take care of the specific implementation of back-end APIs.
Each time a new bunch of data is sent from the server to the Store Manager a set of Issue Models is created.
An Issue Model is the logical representation of each issue, and it consists of a unique identifier, the title, a cover image and the release date. Other information can be provided according to the application characteristics: e.g. a set of image previews, a short description of the issue, a table of contents, etc.
note:It is important to note that the Issue Model is characterized by a set of fields and only a subset of these is assigned by the store. Other information can be acquired from other sources: e.g. the price can be retrieved from the In App Purchase system, or the information that the product has been already purchased and downloaded from a local repository in the application data area. That’s why in the diagram below we decided to attach the Issue Models representation to a Local Storage block.
As soon as a new Issue Model is created by the Store Manager, it is annotated with few extra info collected from the Local Storage. The natural choice for the Local Storage would be to use the Core Data framework but of course a more simple approach based on plists or a serialized version of the data model.
The Store View is a view controller dedicated to provide the Store UI.
note:While the Store Manager is a highly reusable component, the Store View is customized according to publisher requests: we can have a shelf view (as in iBooks) or a sliding covers view, or a cover flow effect. In order to decouple the model data from the view the Store View can talk with the Store Manager using a delegate protocol.
Besides the Store View needs to listen to some Store Manager changes using a central notification mechanism or key-value observing (KVO). Why this requirement? because even if in most cases the Store View gets its data by querying the Store Manager block, using its delegate protocol (e.g. number of categories, name of categories, number of issues per category, name of issues, cover image and so on), it may happen that some events occur asynchronously with respect to the typical UI interaction (e.g.: a user is reading an issue but at the same the app finish to download another issue): in such case the Store View controller must be informed of this particular event in order to update the UI appropriately. Once the Store View knows, through notification or by KVO observation, that something changed in the Store Manager, it can start the delegate protocol based query cycle to update the UI.
The Library View is also a View Controller which is similar to the Store View but customized for the purpose of displaying only issues that have been purchased. It still needs to communicate with the Store Manager using the same protocol used by Store View and it still needs to listen to Store Manager changes, but the set of actions available to the user is completely different. As soon as a purchase is done, that is the transaction has been recorded, there are a set of operations that could be deferred or could simply fail due to temporary networking issues: they are the download phase (which could take several minutes especially if the issue a several hundred megabytes package) and the installation phase (typically unarchiving the package, generating thumbnails and so on). So the Library Manager needs to expose to the user the next required action: download, if the issue has been purchased but not downloaded, stop/cancel download if issue download is in progress, install if the package has been downloaded but not installed and finally read to start reading the magazine.
In the diagram we kept the Store and Library views separated to emphasize the different requirements and to be coherent with the 3-screens based app organization. But as stated before it may happen that the Store View and the Library View are merged in a unique view controller; this approach is common to many well-known magazine apps in the App Store.
note:The Store Manager maintains an interaction with two internet-based Apple services: In App Purchase (via Store Kit framework) and Newsstand (currently in beta, will be available with iOS5).
Due to App Store rules, In App Purchase is practically the only way to purchase magazines from the store. As there is no way at the moment to let the publisher own back-end server to communicate directly with the In App Purchase system, the Store Manager block must be able to annotate the Issue Model with the extra pricing info coming from the In App Purchase server.
The recommendation in such case is to insert an intermediate layer between the Store Manager and the Store Kit framework, whose purpose is to manage the communication with the highly asynchronous Store Kit protocol thus giving at the same time a simple interface to the Store Manager (e.g.: is this issue available in the store? what is the current price in this country? did the user already purchased the issue?) One example of well-known and excellent layer is the MKStoreKit open-source library available from GitHub.
Newsstand is a new feature coming with iOS5. As we are constrained by the NDA with Apple, we cannot disclose too many details and just refer to the marketing info available in the Apple web site. Essentially Newsstand will be a central hub for all subscription-based magazine apps: it is a special Springboard folder that will collect all information from the magazine apps and show and download all the latest issues. The Store Manager must provide the minimum required interface to provide the app the compatibility with this new feature.
In the next articles I will provide some more detail about the construction of the different blocks. We’ll see the details of the Store Manager delegate protocols, we’ll discuss the model behind each issue and we’ll see how to efficiently retrieve information from the network.