Cymraeg Back to the CV

Duplia, Lead iOS Engineer

Tagstr

A rebuild of a social photo app, where the hardest problem was not the feed but the uploads behind it.

Freelance contract of three months, extended to six.

The app, reconstructed

This is a reconstruction, not a recording. Tagstr no longer exists, so the phone is redrawn from two frames of its original promo video. The feed header and the photo editor follow those frames. The camera screen and the tab bar are what Rob remembers, and four of the six feed photos are generated stand-ins.

The animation follows one post from start to finish: the feed, the plus button, a photo taken in the app’s own camera, and a filter applied to it.

The feed scrolls, the plus button opens the camera, the shutter takes a photo of a coffee cup, the filter thumbnails fill in, and the editor switches it from Original to the Sunkissed filter.

What the user does, and what the app does in the background

Requirement: capture and upload always smooth on an iPhone 4. No spinners, no blocking, no waiting.

coral marks an interruption and where the work picks up again

A · what the user does

Capture

Tap +, camera opens Photo taken
Full size original, kept asidenever used for display work duplicated, cropped downOne cropevery duplicate below comes from it
Large preview Thumbnails, one per filterthe same photo under each filter
Editor, pushed on from the rightback is live from the first momenttap a thumbnail, the large preview takes that filter

B · what the app does in the background

The thumbnail queue

NSOperationQueue one unit of work per thumbnail, independent, individually cancellable, finished results cached

finished, kept and cached back pressed mid buildwork in flight cancelled on return, the queue picks up from the next unbuilt thumbnail app sent to the backgroundqueue suspends, resumes on return

Stress tested by capturing and popping back, repeatedly and rapidly.

After back, the photo just taken waits in the corner of the camera screen. Tapping it returns to the editor, with the finished thumbnails still there. the photo just taken

C · the split

Done

User presses Done

What the user does

Tap + Photo Editor Done

the loop keeps turning, whatever the queue is doing

What the app does in the background

The upload queue

sent

the front one is being sent, then it leaves the queue

newest joins the back, in the order they were added

D · what the app does in the background · Core Data

Relaunch after the app is killed

App killed outright, mid process

On relaunch, read the stored state for each item
Processed and cropped?
no resume image processing and cropping
yes
Filter applied?
no resume filter application
yes
yyyy-mm-ddUploaded?
no resume upload of the post, rejoining the upload queue
yes
Nothing to do

items still waiting were listed on a screen of uploads pending or in progress

Drawn from Rob’s recollection; no source code survives.

The brief

Tagstr was a social app built around imagery and hashtags. Version 1 was a fast proof of concept that had done its job and could carry the product no further.

Version 2 was a rebuild, not a refactor: about 80% of the codebase, covering architecture, performance and the interface together.

The hard part

The hard problem was not the feed. It was sending large files without ever making anyone wait: a photo app is at its least usable exactly when someone has just captured something, and the obvious implementation blocks them until the upload finishes.

So uploads were queued and run in the background, and the app stayed usable while they ran. What made it genuinely hard was interruption: an upload had to survive the app being killed mid-transfer and carry on from the stage it had reached. That turns a background upload into a piece of state management with a durability requirement.

The filter strip

Taking a photo opened an editor with the picture full screen and a strip of thumbnails beneath it, each showing that same photo under a different filter. Every thumbnail meant copying a large image, cropping it, compressing it and filtering it, on an iPhone 4.

Nothing could be kept in memory for long, so pressing back released the editor. The thumbnails were built on an NSOperation queue owned by a filter options manager outside it, which is what let finished thumbnails survive: on return the queue carried on from the next unbuilt filter rather than starting again. The whole strip of about 14 filters filled in about 1.8 seconds, immediate on an iPhone 4S, visibly arriving on an iPhone 4.

The filters came from the CEO, who was also the designer. A companion build that never went to the App Store let him tune the values on the phone itself, because they looked different on glass than on a desktop screen. The values were written down on paper and hard-coded in.

How Instagram did it

Instagram had the same editor to build and answered it differently. Until December 2014, each thumbnail in its filter strip showed the same stock hot air balloon rather than the photo just taken.

That was a sound trade across millions of phones, old and new: one stock image costs nothing to draw even on the slowest of them. Tagstr made the other trade, a real preview of your own photo in every thumbnail, on an iPhone 4.

Both phones below are reconstructions. Instagram’s side reuses the Tagstr editor in Instagram’s blue, so only the thumbnails differ, and its balloon is redrawn from written descriptions, because no screenshot of the strip was found.

Tagstr

Every thumbnail is the photo just taken, under its own filter.

Instagram

Reconstruction. Until December 2014, every thumbnail was the same stock balloon.

Outcome

The rebuild shipped, and the contract was extended past launch on the strength of the delivery.

Behind the build

Rob’s own account of the project, recorded some years after it shipped. 8:37Nothing is requested from YouTube until you press play.

Watch “Behind the Build: The Story of Tagstr” on YouTube