Tumblr for iOS
Update: Tumblr for iOS is now completely native.
After updating the Tumblr application for iOS (and coming across Peter Vidani’s Dribbble shot), I decided to take a stab at seeing how it worked. I ended up using both Crunch (for resource files) and Charles (for network traffic). There’s no real voodoo involved to see how things fit together — most of what I did is covered in this NSScreencast episode.
The first thing you notice when looking through Tumblr’s source
files? 26 different Mustache templates. Yeah, 26 —
and all end with a .html
extension.
I really hadn’t noticed that the timeline was one big UIWebView
when first
playing around with the app — in fact, for awhile (even after finding the
templates) I thought maybe each post in the timeline was its own UIWebView
held inside a native container. Credit where credit is due, it’s an incredibly
nice web interface.
Since all the CSS and JavaScript files are included in the source, I thought it was weird that Mustache.js wasn’t included — and both spin.js and Zepto were — but it actually makes a lot of sense. Behind the scenes, the app’s obviously using the Tumblr API, but the API actually has total control over how the timeline looks and feels. So much so, even the highlighted ribbons in staff posts are done via the API:
The API sends 20 resources at a time (posts from users you follow) for the home
timeline. Mustache templates are then used (probably with
GRMustache
) to create the initial HTML
document. Based on some of the comments in the app’s JavaScript files (which are
incredibly well-commented and easy to read), native code is used to
detect how far the user has scrolled.
Once we reach the end of those 20 posts, the API sends 20 more, which go through
the Mustache templates to become HTML, and JavaScript is used to append those to
the current timeline. The downside to this approach (and I’m sure the engineers
are aware of it — the available code is really well-written) is when a
user agressively tries scrolling through the timeline. Frame rate drops pretty
significantly and scrolling begins to feel sluggish — native containers
like UITableView
have had hundreds (if not thousands) of man-hours spent on
performance and cell reuse for this exact scenario.
While most users won’t ever notice this — I mean, it took me a couple
hours to realize it was a single UIWebView
even after seeing the static source
files — there is another downside. Whenever the user goes back through the
timeline a signifcant amount and then exits the application, it can take a
really long time to reload. The UIWebView
basically has to render the giant
HTML timeline again.
But, this post isn’t about a native versus HTML approach, and I’ve got to admit, it’s pretty cool seeing how well the API and Mustache templates mesh together. Basically the entire “logic” behind how the home timeline is displayed exists in the interaction between the two.
Another interesting find was the lack of .nib
files (which is actually the
opposite of Airbnb’s source). Native UIView
files are obviously used
when the user begins writing a post (along with a really nice tab bar
animation), and are probably written in code. One comment in the
Update: the Storyboard comment actually
refers to
storyboard.tumblr.com.Post.css
file indicates Storyboards are in use or will soon be used
sometime in the future.
For Future Bryan, this is to make Storyboard interviews look right.
Another great takeaway was how the engineers target Retina devices in CSS:
Moving on to other parts in the application, I’m inclined to believe that
pull-to-refresh is native (and, as a side note, I really like the use of images
throughout the UI rather than text). There are also two Core Data .momd
directories included in the source, one of which is named STPersistentCache
.
After some light testing, I’m pretty sure STPersistentCache
caches images
locally after they’ve come across the network twice (at least this was the case
with larger images — which no longer came over the wire). It actually
makes a lot of sense when you think about it: some of the images in the timeline
(or other views) will never be accessed again, but those that have been accessed
two or more times must be somewhat pertinent to the user.
The other .momd
includes 20 entities that make up the basis for the types of
posts a user can make, etc. One of the newer entities is FanMail
— which
has accompanying images in the source — but I was unable to find it when
playing around with the app (although, I haven’t interacted with fans on
Tumblr).
Some other notes include Tumblr’s use of Flurry for
analytics (sends on applicationDidEnterBackground
— standard stuff).
Also, the minimum version supported is iOS 5.0 (checked Info.plist
).
Lastly, I could be completely wrong about some of these details. Crunch and Charles are great tools for seeing assets and network traffic, but they’re not exactly a view source into Tumblr’s Objective-C code. I can say the CSS and JavaScript are incredibly well-written code — within only a couple hours I was able to see how things fit together.