Over the past few days I’ve spent time developing a news and comment reader for Hacker News. I created it for personal use and to scratch my development itch. There are quite a few existing apps for reading hacker news, some quite good, but I myself am a hacker and so why not create something?
Before I get into the details, I want to make a few points. First, Hacker News gets a lot of traffic and it’s not cool to punish the web servers with an insane amour of requests. While HN does expose RSS feeds, the feed content doesn’t match up with the page content and there is no feed for comments (and rightly so). Comments are best part of HN. Secondly, this app fetches HTML directly from HN and parses the response. This is not an ideal solution at all because the parsing code is at the mercy of the HTML and site design. Any change on the site breaks could break parsing code. This is a hacker solution. Third, I don’t handle sign on or comment posting. This is a reader application only.
The architecture of the app is very straightforward. A view controller handles the display of entries through the use of a table view. A model abstracts away network request and response parsing and exposes properties representing the parses data. The view instantiates the model, observes changes on the properties representing data to display (in this case entries) through key value coding. Overall architecture looks a little something like this:
The properties the model exposes depend on structure of the data. In this case, the model exposes an
NSArray of entries, where each entry is an
HNEntry object. Each view controller in the hierarchy owns its own model specific to the data being displayed (entries or comments). This isn’t strict MVC but it’s a design decision works well for this app. If the app grew much larger I might want to consider a singleton model which managed both entries and comments and cached data. The view controller instantiates the model, observes the entries and error properties of the model, and then informs the model to request data and begin parsing. This is also not strictly MVC. I find it works well from the view controller perspective each VC is in charge of when and how data is loaded. The view is a table view and a segmented control inside a toolbar. The segmented control let’s you switch between the front page, newest page, and best page. Interacting with the segmented control causes the view controller to request data from the model for the corresponding segment or page. The model retrieves and parses data and sets either the error or entries property. The controller, observing changes on both these properties, will then either display an error message or animate in updated table cells.
The following through the application like so:
Selecting the last table cell causes the view controller request the next thirty entries from the model. The model parses and pushes on the newest entries and the view controller reloads, now with sixty entries. Animation gets a bit tricky here because I don’t want to show the ‘Load More…’ cell if there are no stories and because I only want to animate in the new cells. Direction of animation needs to be considered too. When you select an entry the view controller pushes on a comments controller. The comments controller is another table view controller and shows one cell for the entry at the top followed by zero or more comments cells. A comment cell uses UILabels to display text. Because I am dynamically adjusting the label frame size to display the full comment, the text needs to be resized and gets distorted. I should be leveraging attributed strings here to display full rich text comments. You can read the linked to story by selecting the entry cell and pushing on a web view controller. I am not doing anything special aside from using the default web view. I do not handle the back button.
Since I am not much of a designer, I try to push myself to create something beyond the standard look and feel. I use the same techniques from app to app. I have some methods for drawing gradients which are part of SSToolkit. I use a ShadowTableView to display shadows at the top and bottom of the table view. I use custom views for cell background and selection, and draw gradients inside these views. I try to use gradients everywhere but not overdo it, if thats possible. Rarely do you see a solid color in a well designed app; the colors and textures are just there and feel natural.
The app is universal and rather than subclassing view controllers for both platforms, I made use of the
UI_USER_INTERFACE_IDIOM() macro and branch accordingly. It also helps that I use table views and split views as these work quite well together for sharing code between platforms. I can use the same models and have the view controllers decide how to draw and frame the views based on the device.