A Happy Announcement

I’m very glad to finally be able to share this good news publicly: my husband and I are expecting our second child in October! ?

We’re so excited to become a family of four (plus corgi). We keep telling Charlie he’s going to be a big brother, but he hasn’t quite grasped it yet. However, whenever he sees a baby he says “awww,” so that’s promising. ?

So then, the reason I haven’t been around as much is because I’ve been sleeping. A lot. Like, every chance I can get. For some women, one of the primary characteristics of the first trimester is a sort of soul-crushing exhaustion. Kinda like when you take a NyQuil and you can’t fight off that heavy, drowsy feeling, except all day long.

I haven’t made any progress on Snapthread, but that’s okay. I’m still hoping to get another crash fix update out as well as a big revamp of the title cards before the baby arrives. We’ll see how it goes!

I got to see our little jellybean via ultrasound this morning and was reminded anew of all the positive ways technology can enrich our lives. There’s a lot of crappy things going on in the tech world right now, but something about watching a tiny heart beat in hazy monochrome on a beige-bezeled hospital monitor makes it all melt away. I’m grateful for that.

Status

I know I’ve been kind of MIA lately, but I have a good reason (that I’m not quite ready to discuss). There have certainly been a lot of fun Apple rumors swirling around lately and I wish I had time to blog about them, but alas, I do not. I’m enjoying all of your hot takes though!

Status

It’s been another rough week of receiving bug reports that I can’t seem to reproduce. Don’t ever make a video app, folks. There are just too many variables.

Saving Abandoned Projects

I keep the Xcode project for every app that I start, even if I abandon an idea, because my old projects are often good sources of useful code snippets. Here are a couple projects I started a long time ago that will never see the light of day:

Bear in Mind

 Bear in Mind was the first personal (non-tutorial) project I ever started working on. It was going to be a visual reminder app. Instead of a table view with a list of phrases, its main screen was a collection view of circular photos. My primary reasoning behind it was that a photo might trigger a more vivid, emotional response in my brain, making me more likely to remember whatever it was I wanted to remember. Photos could be categorized by setting a colored border around them. In the future I wanted to add a voice reminder option, so that if you tapped on a photo, you’d hear yourself talking. For example, I could put a photo of my mom and a voice message that said “remember Mom’s birthday!” or something.

I could barely get the app to compile due to a million Swift conversion errors, however after commenting out a bunch of error-filled code, I was able to get it to run long enough to grab a screenshot.

Cloudburst

Cloudburst
Cloudburst was going to be a weather app for photographers. It would include the day’s conditions, when you could catch the best light, as well as daily tips and tricks. I abandoned Cloudburst after considering 1) the cost of maintaining a weather app and 2) the proliferation of similar apps on the App Store that were already pretty polished.

Lessons Learned

Both apps were great learning experiences. Bear in Mind was my first introduction to Core Data and scheduling notifications. Cloudburst was my first experience working with web APIs, UIPageViewController, and stack views. I also learned how to animate the opacity of views. Perhaps my most useful abandoned project was LiveRotate, my app for rotating Live Photos that I removed from sale prior to the release of iOS 10. I was able to use huge swaths of code from that app in Snapthread, saving me from reinventing the wheel.

You’ll notice I didn’t include my game, Corgi Corral, in this list. That’s because I refuse to acknowledge it as abandoned. I’m determined to get it on the App Store someday. I just need to completely re-do its core mechanics and make its icon and menu screen not look terrible, that’s all. Piece of cake! :)

Snapthread and the Terrible, Horrible, No Good, Very Bad Data Model

I may not have been a complete novice when I sat down to create Snapthread, but it’s obvious I didn’t put much thought into its data model.

Basically, I created a class called “Video” which had properties like “asset” (for its AVAsset), “orientation,” whether or not it should be muted, its start time, duration, etc.

The flow from selecting videos to seeing a preview of them threaded together goes like this:

  1. User taps on one or more videos and taps the “done” button
  2. The PHAssets for the selected videos are passed to the main view controller by means of a delegate and stored in an array called “videoAssets.”
  3. The videoAssets array is used for two things: 1) generating thumbnails for the video timeline and 2) fetching the actual AVAssets for all of the selected videos and wrapping them in the Video class. The Video objects are stored in a new array called “clips.”

You can already see a big problem here. I have two arrays to maintain: an array of PHAssets and an array of Video (containing the AVAssets). If a user re-orders videos in the timeline, I have to re-order both arrays. It’s mind-numbingly stupid.

It gets even dumber. I decided to add titles to Snapthread, so I added an enum called “VideoType” and just shoe-horned all the title stuff into the Video class. Now my “clips” array could have Video objects that were of type “.video” or “.title.” But wait, what about the array of PHAssets? I can’t create a PHAsset for a title card.

So, I shrugged and decided users could only add a single title at the beginning of the movie so that I could do stuff like “clips.remove[indexPath.item + 1],” taking into account the title card. It’s so, so gross.

Going Forward

My proposal for a new data model is to create a protocol called “Threadable,” which will cover any component of a user’s movie that can be added to the timeline. Whether it’s a video, title card, or still photo (which I may add support for in the future), it needs to give me two pieces of data:

  1. a thumbnail representation of itself
  2. an AVAsset to insert into the composition (for titles, this is a short blank video that’s included in Snapthread’s bundle)

All of the rest of the media-specific details will go in Video, Title, and (maybe) Photo classes. Then, I’ll have a single array of type “Threadable” which will be a million times easier to deal with.

I never really understood the benefit of protocols until this idea hit me the other night. Now I totally get it!

February Whirlwind

I realize February is the shortest month of the year, that it’s not even over yet, and that saying things like this is super cliché, but: holy cow this month went by fast.

Snapthread was featured on the App Store on the 12th and it still doesn’t seem real. It’s definitely been a fun couple of weeks. Every morning my husband waits anxiously for me to wake up so he can report Snapthread’s current ranking on the charts. At its peak, it hit #14 in the Photo & Video category and #51 on Top Paid Apps (it’s now around #104 in Photo & Video).

It’s not like I made tons of money in the last two weeks but I did make some money, which is more than I can really say for the past four years of learning iOS development. According to App Annie, in the last 30 days Snapthread was downloaded 1,424 (!) times. As soon as it’s no longer featured, I expect those numbers to fall right off a cliff; still, I’m super happy with how well it’s doing and am enjoying these feelings of success, however fleeting they may be.

As I type this, Application Loader is churning away on the first archived build of version 1.6, which adds iPad support. It’ll probably be a few days before it gets through beta review, but if you’re interested in testing Snapthread on iPad, please get in touch!

After iPad support, I hope to finish a revamped title card system before taking a break for a little while. Thanks to everyone who has shared Snapthread, left ratings/reviews, helped me out with programming questions, or just sent kind words and encouragement. This is such an awesome community and I’m proud to be a part of it!

Status

Charlie has found two new favorite games on his iPad (my old third gen), both of which are by Sago Mini: Sago Mini Farm and Sago Mini Puppy Preschool. In the latter, he especially loves putting all the doggies in the bathtub. ???

Status

I know, I know. I said I was going to take a break from programming in February. But then Snapthread got featured and I got all jazzed about it and well…here I am. Here’s a peek at my work-in-progress:

Early version of Snapthread for iPad

Status

Snapthread received 8,194,268 impressions over the last 3 days, in case any of you are interested in that data. That’s basically the number of people who opened the “Apps” tab in the store, since AFAIK you didn’t have to scroll at all to see it. It only translated to a few hundred downloads, but I’m still extremely pleased!

Status

Is there any way I can detect when a UISplitViewController has changed display mode? I need to refresh my collection view after it finishes changing from primaryOverlay to allVisible. There’s no delegate method for that that I can see.

Status

? In the week since I posted about Snapthread’s download numbers, it’s actually done quite a bit better than I expected. I thought it would drop off to 1-2 downloads/day, but instead it’s been more like 8-9 (and one day had 22!). I still think moving to freemium is the best way forward, though.

Status

Pro-tip: if you’re localizing your app yourself and you need to know what Apple calls a certain thing in that language (i.e. “Smart Albums”), just find a support article that mentions it and change your locale at the bottom of the page.

Status

I’ve been having quite a lot of fun localizing Snapthread with the help of some very generous translators. I’m copy & pasting the translations manually and it’s definitely hitting the “mindless data entry” sweet spot for me. Very relaxing.