Journey to 2.0: Market Appeal

Snapthread’s journey to version 2.0 has been one of gradually broadening market appeal. If you recall, version 1.0 was an extremely niche product, aimed at people who took lots of short, vertical videos and wanted to merge them together. Over time I added the ability to merge Live Photos, and then added support for landscape videos. I thought I’d market Snapthread as a cool app for stitching Live Photos together, but quickly learned that even Live Photos are pretty niche.

Recently, after spending a couple hours studying the top charts in the Photo/Video category, I realized that Snapthread could be a great, useful app for just about everybody. In the reviews of some top video editing apps, users bemoaned shady subscription practices, being constantly nagged to buy in-app purchases, and being asked to give 5-star ratings in order to use features (for the record, it’s impossible for devs to unlock features based on star rating). I don’t do any of those things with Snapthread. In fact, Snapthread doesn’t collect any analytics, store any user data, or contain any subscription options. Just a plain old “premium unlock” IAP and, in 2.0, a tip jar.

Based on my research, I know there are some things I need to do to help Snapthread gain exposure. I need to add “Video Editor” to Snapthread’s name to help it show up in search results. I need to add “slideshow maker” to its keywords, because apparently people are hungry for simple slideshow creation apps. Despite Apple’s guidelines, I need to add device frames and descriptions to my App Store screenshots, because that’s what all my competitors do (including Clips by Apple).

I also need a new elevator pitch. The app isn’t “just” for Live Photos anymore. So what is Snapthread? Snapthread is a simple, casual video editor and slideshow maker that works with videos, still images, and Live Photos. It’s fun, fast, and user-friendly.

So how will Snapthread 2.0 compare to Clips, which is free?

  • Snapthread supports multiple aspect ratios (portrait, landscape, or square); Clips only supports square.
  • Snapthread imports Live Photos as videos; Clips treats Live Photos as still images.
  • Snapthread allows you to mute, loop, bounce, rotate, trim, and crop clips; Clips supports muting and trimming.
  • Snapthread doesn’t have project management or an in-app camera.
  • Clips has Live Titles, selfie scenes, animated title posters and stickers; Snapthread has non-animated title posters.
  • Both apps only support one music track per video.
  • Neither app has options for transitions between videos (i.e. wipe, cross-dissolve, etc.)

I’m going to do my best to continue to improve Snapthread with things like stickers and transitions, and the ability to select a specific portion of a music track.

This shift in thinking about Snapthread has been exciting for me, and I’m really looking forward to marketing it as a mass market product.


I was reminded how important documentation is today after spending fifteen minutes trying to figure out why a certain code path wasn’t being reached.

If you shuffle between UIImage, CIImage, and CGImage a lot, you might be tempted to access the handy “.ciImage” property of a UIImage. However, that property definitely does NOT have a value if you initialized your UIImage from a CGImage, and you need to use a CIImage initializer instead. Thanks, Apple docs!

Journey to 2.0: Container View Controllers

One of the major structural changes I need to accomplish for Snapthread 2.0 is switching to the use of container view controllers. For those who don’t know, container view controllers allow you to embed one or more view controllers inside a parent view controller, which can then manage transitions between its children. UINavigationController and UITabBarController are examples of container view controllers in UIKit, but you can also create your own.

I’ve never used custom container view controllers before, so of course I hit Google to see what I could find. John Sundell has a great introduction to the topic and I really liked the series by Mike Woelmer as well. (Edit: I also meant to include this fantastic article by Ben Sandofsky) The first thing I learned was that if you want to be able to switch between child view controllers, you should probably set them up in code instead of Interface Builder, which only allows a single embed segue between parent and child. I wasn’t ready for that though, so I decided to take a baby step and find a situation where a single parent-child relationship made sense.

Snapthread’s main view controller is…well, massive. I’m too embarrassed to tell you how many lines of code it is, but after combing through it, I realized at least 400 lines were devoted to setting up the AVPlayer, handling play/pause events, observing the status of the current AVPlayerItem, scrubbing, adding the watermark, etc. Clearly, the video player was a good candidate for having its own view controller.

So, I created a VideoPlayerViewController class and began copy and pasting everything relevant to setting up the AVPlayerLayer, displaying time elapsed/remaining, scrubbing, etc. In Interface Builder, I added a new view controller and copied over the video preview view, which is a custom UIView class that resizes its own AVPlayerLayer, and the player controls.

I deleted the video player and controls from my main view controller and replaced it with a container view from the Object Library. I hooked it up to my new view controller using an embed segue.

Next, I had to figure out how to communicate between my main view controller and the video player. Communicating between the player and its parent was easy; I just set up a delegate with methods for responding to changes in AVPlayerItem status and duration (if it exceeds a certain duration, the UI displays a warning that the user needs to purchase Premium in order to export). I set the delegate using prepare(for segue:), which is called when the child VC is embedded.

There were times when I needed to tell the player to do something from the main view controller, however, such as hide its controls or clear its watermark. I wasn’t quite sure how to handle that. Using notifications was one option, but it just didn’t feel right for some reason. I ended up storing a reference to my VideoPlayerViewController and referencing it directly. That’s probably bad practice, but I’m pretty sure it’ll be okay, as I don’t plan on using that particular video player with any other view controller.

Overall, I feel slightly more comfortable using container views now, and I think I’m ready to tackle the next step: transitioning between child view controllers. I plan to post more about new things I’m learning; each of those posts will be prefaced by “Journey to 2.0” if you’re interested (or want to ignore them, lol).

Organizing 2019 with Capsicum

I’ve never been a heavy user of task management apps. I use Reminders for things like our shared shopping list and occasional to-dos and make checklists in Notes for features I want to add to Snapthread. I don’t use a bug tracker, I don’t track any of my habits, and I don’t do any daily journaling. There are many beautifully-crafted apps that are well-suited to accomplish each of those tasks, but the cognitive load involved with getting started is just too much for me right now. That’s why I was excited when developer Ish ShaBazz and designer Heidi Helen Pilypas announced that they were creating a new kind of digital planner called Capsicum.

Screenshot of Capsicum's daily view

Capsicum is like a daily planner, to-do list, habit tracker, and notebook all rolled into one. It takes me back to the days when I would linger in that corner of Barnes & Noble near the registers, the one with all the notebooks and calendars and Moleskines, and drool over all the beautiful planners I couldn’t afford. Capsicum is all about customization and aesthetics: you can choose a cover for your planner, select a primary color and style for the decorative “tape” that divides each section, choose from a fun variety of fonts for headings, and more.

Maybe that’s what I love most about it—the skeuomorphic design. When you open your planner, it literally looks like a paper planner (well, if a paper planner could magically show you the local weather forecast at the top of the page!). When you flip between days, it uses that nice page curl animation. The tabs that allow you to switch between daily, weekly, and monthly views look like real notebook tabs. It’s delightful!

I joined the Capsicum beta early on in its development, but couldn’t quite figure out how it could fit into my daily life. Then, a few weeks ago, something finally clicked.

Habit Tracking

I had been feeling a bit discouraged about how little time I had to blog, work on Snapthread, and generally do things that I enjoy. However, I was simultaneously encouraged that I was finally able to complete a year-long Bible reading plan in 2018. It then dawned on me that if I was able to inch my way through the Bible a few chapters at a time for 365 days, I could similarly work toward other goals in my life by completing a bunch of really small tasks.

I set up a list of things I wanted to track in the Habit Tracking section of Capsicum—things that would improve my health, like eating fish (apologies to my vegetarian readers) and flossing my teeth, and things that would make me feel happy and accomplished, like writing code and blog posts. I don’t have any particular goals in mind, I just want to track how often I do all of those things and see if the numbers themselves might either motivate or encourage me. So far it’s motivated me to open Xcode and make little tweaks to Snapthread, even if just for five or ten minutes, nearly every day this month. It may not be much, but it’s something I can feel good about.

Screenshot of habit tracking in Capsicum
Yes, I changed my notebook color just for this screenshot


I don’t think Ish and Heidi meant for Capsicum to be used as a daily journal, but I’ve found myself jotting little anecdotes in the Notes section below my daily to-do list. They’re mostly funny things Charlie said or did, and honestly I’m not really sure why I’m doing it because there’s no easy way to go back and view them. However, I’ve failed at every other attempt to use an app like Day One or even a paper journal, so, I guess it’s better than nothing!

App Development

It’s not that I don’t try to keep track of bugs and feature requests for Snapthread. It’s that they’re stupidly spread out in a bunch of different places. Some of them are e-mails flagged as important, others are scribbled in a paper notebook next to my recliner, and still others live in a checklist in Notes. Yeah. It’s ugly, folks. I decided to consolidate that mess into two checklists in the “Loose Leaf” section of Capsicum. That way, they live extremely close to my daily to-do list, which is just a couple tabs away. I can simply look at my feature request list, break a feature down into bite-sized tasks, and add those tasks to my to-do list.


I really love Capsicum’s daily, weekly, and monthly views. The daily to-do list is nice enough, but when I switch to the weekly tab I can see all the things I accomplished (or didn’t) for the entire week. The monthly tab allows me to set goals for the month and see a list of birthdays. Capsicum will optionally migrate unfinished tasks to the next day which is handy for filling me with shame (How many more days will I push off writing that thank you card to my aunt? 😭).

What I’ve learned from using Capsicum throughout the past few weeks is that I value the simplicity and convenience of having all these functions in one place over the robust feature sets of separate apps. It makes me happy to hear that Ish and Heidi are planning to add even more “modules” to Capsicum in the future.

Capsicum is available as a $1.99/month or $19.99/year subscription, with a 14-day free trial. From what I understand, you are not automatically charged at the end of the trial, so you can check it out without worrying about canceling if it’s not for you. If it is for you, make sure you give it some App Store rating/review love! It helps us indies out a lot.

2.0 Design Goals

Happy New Year! 🎊 I hope 2019 is off to a good start for you. I’ve been slowly getting back into coding since my daughter was born, sneaking in 30 minutes here and there in the evenings after the kids are asleep. I’m hoping to get Snapthread 1.9 submitted soon; it contains bug fixes, rudimentary support for still photos, the ability to loop clips, and makes the app compatible with the new iPad Pro screen sizes.

That said, I’m already thinking about Snapthread’s big 2.0 update. I don’t usually do “major releases” because I prefer to get new features out quickly, but now feels like the right time to slow down and really do a lot of work and polishing. A big update also invites more press coverage, is an opportunity for marketing, and can get Apple’s attention…gotta work toward that Apple Design Award, you know. 😜

My design goals for Snapthread 2.0 are simple and twofold:

  1. Improve accessibility. This will involve making my buttons even more button-y and using text labels in addition to icons for added clarity.
  2. Consolidate functions. Currently, every tool for editing a clip opens up its own modal view, with its own video preview. My goal is to make the clip editing interface more modular, swapping out tools below the same preview so that all editing (muting, cropping, trimming, looping, etc.) happens in the same view controller.

There are many more additional improvements that I’m hoping to cram into 2.0…but we’ll see. Some of them include: video transitions, the ability to add text to clips, Ken Burns effect for still photos, non-buggy support for time-lapse and slow motion videos, and auto-saving of recent projects to guard against losing work. I also want to continue improving the title card selections.

In order to finish 2.0, I’m going to need a good task management app. After watching the beta evolve over the past year, I believe Capsicum by Illuminated Bits may be the best app for helping me accomplish my goals this year. My next post will be all about how I plan to use it!

iPad Pro (2018) Impressions

(to the tune of Rudolph the Red-nosed Reindeer)
You know ‘Ticci and Gruber, @panzer and Ritchie
Marco and Jason, Joe and Rosemary
But do you recall, the most famous YouTuber of all?
MKB(in)HD, had a very shiny Pro…

Um, so, yeah. A bunch of great iPad Pro reviews/impressions have trickled out over the past few weeks—so many in fact that I was hesitant to even write my own. I agree with much of what has already been expressed: the hardware is great, the software has numerous pain points, and the answer to “can this device replace your laptop?” is the same as it’s always been, which is “yep, maybe, probably not.” Yep for a ton of people that use computers for light work and entertainment, maybe for professionals in certain fields or with particular priorities and workflows, and probably not for the rest.

As an iOS developer, I’m forced into the “probably not” category until something resembling Xcode makes its debut on iOS. However, as a blogger, amateur photographer, and consumer of fine internet content (gross, sorry), the iPad meets my needs just fine. Here’s my thumbs up/thumbs down for the third generation iPad Pro.

My Config

I ordered a 12.9” Pro, 256GB Wi-Fi only model in silver to replace my iPad Air 2. I also bought an Apple Pencil, Smart Keyboard Folio, and an additional rose gold case made by Ztotop which, for $30, is really pretty darn good. It’s sturdy, attaches via magnets like Apple’s cases, is as thin as possible, and comes in colors other than black and white.

Thumbs Up 👍🏻 

As a stay-at-home mom with a two year old and a two month old, the device I use as my primary computer has become a matter of accessibility. What allows me to sneak in tasks quickly? What can I carry around easily with one hand? What makes me seem more approachable and doesn’t create a physical barrier between me and my kids? An iPad is the best fit for this season of my life, so I’m overjoyed that Apple’s latest offering is smaller and more capable than ever.

First off, this device is aces for editing photos. I helped my sister-in-law “fix” her family Christmas card photo this year by lengthening someone’s shirt to cover their midriff. The Apple Pencil made a precise edit like that ridiculously easy. I also edited our own family Christmas card photo, as well as an entire photo book’s worth of pictures of the kids to send to my parents. I know someone’s said this before, but it almost feels like working in a darkroom, dodging and burning the old-fashioned way.

Yesterday my mom asked for a picture of the kids in their Santa jammies in front of the Christmas tree. It worked out better for me to snap a quick portrait of them during the day, but I still wanted to add some colorful bokeh from the tree at night (at which point I sadly realized my camera lens does not create perfectly round bokeh). I used Affinity Photo on my iPad to create this composite, which, while far from perfect, is still pretty cute:

Penny was less than enthused

Messing around with photos on my iPad has made me dream of an iPad model with an even better camera than the iPhone line-up. A “medium format” camera, if you will. Maybe Apple could even offer its own magnetic lens attachments. Shooting and editing using the same big, gorgeous display would be kinda cool I think. /end dream sequence

iOS 12 has improved the experience of transferring photos to an iOS device by leaps and bounds. It used to take forever to load hundreds of thumbnails from an SD card. Now, it’s really pretty snappy. I took a ton of photos at our family Thanksgiving with my Canon DSLR and within seconds was skimming through them on my iPad using the SanDisk USB-C card reader I bought for my MacBook Pro.

My favorite photo editing apps at the moment are Lightroom, Snapseed, and Affinity Photo. I’m also looking forward to the recently-announced Darkroom for iPad, which is currently in beta. Photoshop coming to iPad is more exciting for the role it might play in shaping the OS’s future than for its actual features.

Writing on an iPad Pro is pleasant. I’m currently typing this post in iAWriter using the Smart Keyboard Folio. I like the feel of the folio’s keys, and the dull “thwop” they make when you press them. The viewing angles for the 12.9” model are comfortable (a few people have complained that the angles on the 11” are too steep), and I don’t mind having the keys facing outward when in “tablet mode.” In fact, like Myke Hurley, I rather enjoy drumming on the keys and using them as a sort of fidget toy/musical instrument. (Where do I pick up my #MykeWasRight sticker?)

There’s a lot more to like about the iPad Pro, especially if you’re upgrading from an iPad Air 2 like I did. The display is top-notch, ProMotion is one of those things you don’t understand how you lived without, and the Apple Pencil is downright magical. It’s much heavier than the Air, of course, but still light enough to comfortably pick up with one hand. If you love iPads, don’t own last year’s generation, and have the dough: what are you waiting for? You should buy one.

Thumbs Down 👎🏻 

Look, I’ll be straight with you. This keyboard case is boring as heck. I ended up sticking a small Apple logo sticker on one side along with an ATP sticker to spruce it up a bit. The lack of color options (and case options in general) made me pretty crabby on pre-order day and honestly, I’m still pretty annoyed about it. Like, what is Apple thinking? The creative professionals they’re seemingly targeting with the iPad Pro line are exactly the kind of people who like to buy unique accessories that fit their personality. I just don’t get it.

This is what life with a two year old looks like.

There’s actually very few things I need to do that I can’t do on my iPad. In fact, I can rattle them off rather quickly: I can’t use my preferred banking app, Banktivity, because its iPad app doesn’t allow me to import OFX files; I can’t compare or copy and paste between two Microsoft Word documents side by side (or have multiple tabs of any app besides Safari); I can’t create a slideshow for my church’s weekly service because the presentation software, Proclaim, doesn’t have a full-featured iOS app; and finally, I can’t work on Snapthread.

Of course, there are also a number of tasks that are just plain clumsy on iOS, like discovering keyboard shortcuts (and, as John Gruber recently pointed out, basic functions like “Undo”), shuffling files between apps, managing fonts, and multitasking. All of these things can be improved via software update, and hopefully iOS 13 will address at least a couple of them (though I don’t know about you, but I’m trying to temper my expectations for June).

It’s clear to me that I’ve only scratched the surface of what the iPad Pro can do. Some of that is because the device’s performance potential exceeds its software’s capability. Most of it, however, is that I just don’t know what I’m doing. Matt Cassinelli’s video on iPad gestures is somewhere on my “watch later” list, but aside from that I feel overwhelmed by the number of iPad productivity tips out there.

On a Mac, you can poke around in the menu bar and find all sorts of interesting and useful functions. On an iOS device, exploring isn’t quite as easy, and functions are far from consistent across applications, making it much more difficult (in my opinion) to become an iPad expert than a Mac power user. That’s frustrating.

And then there’s this: to really thrive, the iPad needs a richer ecosystem of pro applications. Besides filling the obvious holes in its software line-up like Logic and Final Cut Pro (also Aperture 4ever ❤️), Apple needs to offer developers more capable APIs and continue to improve its App Store guidelines and practices.

For example: improve the revenue split, aggressively purge scammy apps from the store, stop nitpicking every little thing from developers with a good track record (alternatively, make the guidelines more clear), continue to explore new business models, and make it a helluva lot easier for developers to implement subscriptions. To an outsider like me, this doesn’t seem like rocket science. Perhaps it’s just poor organization, or utter cluelessness, or maybe it’s a stubborn unwillingness to even acknowledge (let alone address) these issues because it might negatively affect the bottom line. Whatever the case, it’s holding iOS back.

I long for a day when iPad reviews aren’t by necessity reviews of iOS. A day when we’re just bickering over specs, colors, ports, and keyboard layouts. Some say we’ll never see such a day while Tim Cook is at the helm. I prefer to remain optimistic. 2019 will be the year, I just know it. 2019, y’all. You’ll see.

I think.

Well, I mean, maybe.

Penny Rose

Nothing reminds me of the steady, relentless march of time so acutely as having a newborn baby (well, except maybe having a blog that I don’t update often enough 😅).

Penelope Rose Hansmeyer was born on October 15 via a scheduled cesarean section. For those interested, she was 7 pounds, 8 ounces and 19 inches long. Everything to do with her birth went incredibly smoothly—a stark but welcome contrast to my son’s birth two and a half years ago! And speaking of Charlie: he’s adjusted really well so far to having a baby sister. He calls her “Baby Penny” and likes to pet her hair (which, holy cow, she has a lot of hair!).

I’ve been incredibly blessed not to experience some of the darker challenges of motherhood, such as postpartum depression and difficulties with breastfeeding. Charlie was a terrible sleeper which resulted in us co-sleeping for over two years, and I guess time will tell with Penny, but overall I just feel overwhelmingly happy with my little family and our humble little life.

I just looked back at my post about Charlie’s birth and realized he was born shortly before the Apple special event which introduced the iPhone SE and 9.7″ iPad Pro. It’s fitting, then, that Penny was also born shortly before a special Apple event. I didn’t quite get my order in before the shipping dates slipped, but I’m looking forward to receiving a silver 12.9″ iPad Pro with Apple Pencil sometime before the 20th. It sounds like an amazing upgrade from my iPad Air 2, and I can’t wait to share my impressions with you.

In the meantime, though, I’m gonna cuddle with this little pumpkin. 😊


The Sweet Setup Review

The Sweet Setup Reviews Snapthread

I love this review of Snapthread by Josh Ginter, especially this paragraph:

These backdrops and Creative Commons music options are, again, very plain and simple. However, the point of the app is to be a quick and easy way to share Live Photos with non-iPhone users and with a little extra pizazz. Snapthread is not designed to replace iMovie, so feel free to export your video after the Live Photo conversion and do more major edits inside iMovie.

Josh really nails what Snapthread is all about: it’s meant to be simple and fast, with a few little extras for those who really want them. I’d absolutely advise people who want more control over music, titles, and other effects to continue editing in a more fully-featured editor like iMovie. I’ll continue to add more editing functions as time goes on, but my intention has always been to compete with super casual apps like Clips rather than bigger apps like iMovie.

I Forgot to Take Videos

I forgot to take videos for the first few days after my son Charlie was born. I made sure to pack a couple nice cameras in my hospital bag, and recall struggling against the harsh lighting in my recovery room (not to mention the constant stinging of my incision) to snap some semi-decent photos of my new little bundle. It felt like enough at the time, though now I wish I had done a little more.

Maybe I should have shelled out for the professional photographer. I definitely should have insisted my husband take more pictures of me holding Charlie. And I should have taken some videos, too. Over the past two years countless friends have had babies, and many of them took videos of some of their earliest moments. I find myself wishing I had done the same.

In a way though, I did. I was using an iPhone 6s when Charlie was born. I took a few photos of him at the hospital to easily send to family and friends, and of course took many [thousands] once we finally got home. I’ve always had Live Photos enabled, so each one of those snapshots recorded a tiny 3-second clip.

The clips are shaky, low-quality, and mostly lack sound (because the little guy was sleeping), but there’s just something about them. I’m glad they’re there. They add some “concreteness” to a time of my life that seems like a blur, in a way that a photo alone couldn’t quite accomplish.

When I’m considering how to record a moment, I almost always favor photographs over videos. After all, you can’t really hang a video on your wall. Live Photos make that choice even easier, and with an app like Snapthread, I can still salvage a great moment from a sub-par photo.

My hope for the future of Live Photos is that we won’t have to choose between taking the highest quality photo and capturing those precious little videos. Having portrait mode and adjustable depth data is amazing, but hearing my little boy’s laugh years later is perhaps even more so.

If all goes according to plan, I’ll be going in for a scheduled cesarean section two weeks from tomorrow and we’ll finally get to meet our little girl. You can bet I’ll be taking even more Live Photos (and longer videos too) this time around.

If you use Snapthread to share some of your favorite moments publicly, I’d love it if you’d use the hashtag #snapthread or tag @snapthread (either on Twitter or Instagram) in your post so I can find them. And if you’ve written an article or blog post about how Live Photos in general have affected your life, I’d love to read that too!


Marzipan on Mojave

Benjamin Mayo on Marzipan

Marzipan apps are ugly ducklings. As soon as you use them, you can just know these are not at one with the system. You detect that there’s a translation layer of some kind at work here, just like when you use Slack on the Mac you instinctively feel that it’s a web app in a thin wrapper. The underlying implementation is exposed to the user with a bevy of performance sluggishness, UI quirks and non-standard behaviours. That’s bad.

Awhile ago I wrote about Marzipan and included a crowdsourced list of “what makes a Mac app a Mac app.” It was a pretty comprehensive list, yet lacking in minor details. I knew there had to be a bunch of nitpicky visual annoyances and UI oddities, and Benjamin covers those really well in his post. I feel like I have a much better understanding now of what needs to happen for Marzipan apps to feel native on the Mac.



Here’s the new 40mm Apple Watch Series 4 on my tiny 6-inch wrist next to my original Series 0, and then on its own with my old Rose Red band attached to it (please ignore the weird white balance difference…the super pale one is correct).

Watch Series 0 to Series 4 Comparison

Displaying Photos by Moment with Section Headers

One feature I knew I wanted Snapthread to have from very early on was the ability to display a user’s photo library in a similar way to the native scrolled to the bottom, sorted by Moment, with selectable sections. What I ended up implementing is actually closer to the Photos app within the Xcode device simulator: it can’t “zoom” in and out of Moment clusters, but it can display assets organized in sections by location and date.

I created a sample project to demonstrate how I did that and put it on GitHub. This is the first time I’ve ever shared code on GitHub, and I know it’s not particularly good, but if you run the project on your device you should see just what I described: your most recent photos and videos at the bottom of the collection view, sorted by Moment. The project loads the user’s first 25 Moments immediately, and then performs a background fetch for the rest, refreshing the collection view only if the user scrolls to the top of the currently loaded content.

There might be much better ways to accomplish this. I welcome any feedback!

Here’s the project link again, for those interested: SwiftyPhotoMoments on GitHub.

Moving from Paid Upfront to Freemium: Logistics

If you’re thinking about switching your app’s business model from paid upfront to freemium and, like me, have no experience working with servers, I’m here to tell you that local receipt validation isn’t as horrible as it seems.

If you’re unconcerned about piracy and simply want to check to see which version of your app was originally purchased, I highly recommend following this tutorial by Andrew Bancroft: Local Receipt Validation for iOS in Swift From Start to Finish. What I did was skim through each step of the tutorial first to see what was involved. Then, I grabbed Andrew’s code from GitHub and read more carefully through the tutorial, copying files from his project to mine as needed.

Andrew’s tutorial doesn’t go into detail about how to check for original app version, which is why I’m writing this. Hopefully someone will find it useful!

Every time Snapthread’s main view controller loads, it runs a function called checkIAPStatus(). Here’s what that function does, in pseudocode:

if the “purchasedPremium” UserDefault has been set, don’t do anything because everything is already unlocked

else if a UserDefault that I set in the previous release of Snapthread called “originallyPurchasedPaidVersion” is true, unlock everything and set the “purchasedPremium” default (this covers users who paid upfront and have used Snapthread recently enough to have had the default set)

else retrieve and validate the receipt using the ReceiptValidator class created in the tutorial (it returns a ParsedReceipt struct if successful) and examine it for originally purchased app version

NOTE: One of the most important things to remember is that the receipt doesn’t list the original App Store version number that was purchased (such as 1.0, 1.1, etc.). Instead it lists the original build number. So you’ll have to note the final build number of your paid upfront version and check against that.

When you ask your ReceiptValidator to validate a receipt, it returns an enum that may or may not have an associated value (either .success, with a ParsedReceipt struct, or .error). So you can do a switch statement on the result, and do something like case .success(let receipt): to grab a reference to the associated ParsedReceipt so you can look at it.

The originalAppVersion property of the ParsedReceipt struct is a String, so you’ll want to convert it to an Int in order to do a less-than comparison.

The only real downside, in my opinion, to doing local receipt validation using Andrew’s method is that it uses OpenSSL, which requires you to disable Bitcode in your project because it doesn’t support it. Disabling Bitcode is easy, but can cause you to get a weird e-mail from the App Store after uploading a build telling you you’ve got extra symbol files, or something like that. It’s just a warning and doesn’t prevent your build from going through or anything, but I was confused by it.

So far I haven’t received any complaints from previous purchasers who can’t export long videos or are seeing a watermark, so I’m guessing I must have done something right!