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!

Numbers

It’s been six days since I launched Snapthread 1.5, so I thought I’d share how it went in terms of downloads and revenue.

What I did differently

When I first launched Snapthread back in September, I did so with a blog post and a couple of tweets. Unsurprisingly, it did pretty poorly, with only a download or two per day. Right before Thanksgiving I decided to put it on sale for 99 cents which caused a modest bump in downloads for 4-5 days, but nothing spectacular.

Of course, Snapthread itself wasn’t particularly compelling at that point, since it only supported portrait photos and videos.

For version 1.5, I upped my game a little bit. I put together a new website, created new, more professional-looking screenshots, put together a press kit, set up a Search Ads Advanced campaign, tweeted about it, published a blog post, and e-mailed six media contacts. I also submitted the App Store Editorial form.

How it went

On Monday and Tuesday, several of my awesome Twitter acquaintances tweeted about Snapthread (some of whom have > 10,000 followers). On Wednesday, MacStories published a review. I was confused and excited when it continued to climb the charts in the Photo/Video category on Thursday, not realizing that another article had been published on iMore that morning. Snapthread’s ranking peaked at #108 before falling rapidly off the chart.

Snapthread was also posted to Product Hunt, but didn’t receive enough upvotes to trend.

Honestly, I still feel like a “nobody” in the iOS development world, so getting as much attention as I did for something I created was great fun. But did any of it translate into big downloads and revenue? Not really.

On the day the MacStories article was published, I made about $140. The next day, $103. Yesterday, $36.

What went wrong?

My gut feeling is that it’s just really, really hard to get noticed. Here are a few other guesses:

  • The app just isn’t good enough.
  • People don’t want to spend $2, or it doesn’t provide $2 worth of value.
  • Some folks don’t like Live Photos, or don’t see any use for them.
  • I didn’t e-mail enough people.
  • I didn’t have any videos showing how the app works.

I also didn’t advertise on Facebook or anywhere else because I honestly can’t afford it. I threw a few bucks into a Search Ads campaign which has so far resulted in 1,319 impressions, 22 taps and 1 conversion.

What’s next?

Next, I keep working to make Snapthread so darn good that it can’t be ignored. I chose this life for fun, not profit, so I’m going to keep on having fun and hope that someday I’ll make a profit.

Assumptions vs. Complexity

At one point in episode 112 of Under the Radar (Ideal vs. Pragmatic), Marco and David talk about a dilemma that developers sometimes face: the choice between making an assumption, and exploding complexity. I thought I’d write about some of the times I encountered that fork in the road while building Snapthread, and how I decided to handle it.

My first opportunity to explode complexity reared its head the moment I selected File —> New Project in Xcode. I was immediately presented with the option to use Core Data. I stared at the empty checkbox. Did I want to persist data in Snapthread? Should my users be able to save their projects in order to return to them later?

Data persistence adds a huge layer of complexity to even the simplest apps. If I had decided to let users save their projects, I would have had to save an enormous amount of information in order to later reconstruct a video. And what would happen when I made the app universal? People would expect their projects to sync. I’m writing this post in Writemator 1.0, which doesn’t yet sync via iCloud, and I already wish it did.

In the end, I assumed that Snapthread’s users could complete their work in a single, short app session. They would open Snapthread, throw together a quick video in a matter of minutes, save or share it, and move on. Of course with this approach, Snapthread will never be a pro-level video editor, but that’s fine with me. It saves me a lot of work, and further emphasizes that Snapthread is meant to be fast and casual.

I made two more assumptions later on in Snapthread’s development: 1) that once I positioned the app as a visual studio for Live Photos, people would primarily use it for Live Photos, and 2) that if users did merge standard videos, those videos would be taken with Apple devices. Scaling and translating videos to work in any of 5 possible aspect ratios requires a lot of conditional branching statements. Each possible orientation (portrait, upside down portrait, landscape home button right, landscape home button left, and then all of those options again for the front camera…) ends up needing different translation values in order to position the video correctly. By assuming that a video’s original aspect ratio and pixel dimensions fall within a narrow range of choices, I prevented that tangle of if-elses from becoming completely unmanageable.

Honestly, I think one of the only safe assumptions you can make in software development is that at some point, someone is going to use your product in a way you didn’t anticipate. You can then choose to either address those edge cases, or say “sorry, you’re out of luck.” For instance, apparently you can’t add a soundtrack from your music library in Snapthread if your phone is jailbroken. There’s nothing I can do about that, and if there was, I probably wouldn’t do it.

I also think that if faced with the choice between making an assumption and exploding complexity, you should almost always choose the former. Incorrect assumptions can often be remedied, but it’s hard to dial back complexity. Just look at all the extra crap Facebook has added to Messenger in the past few years. Even if they wanted to simplify the app again, it can’t be easy to tear all that stuff out.

Anyway, it’s something to think about. What are some assumptions you’ve made while developing your apps?

Snapthread 1.5

Snapthread 1.5 is now available! This update brings support for videos and Live Photos taken in landscape orientation. It also features a new icon and a number of small improvements designed to make the movie-creating process as fast, flexible, and simple as possible:

  • You can now square-crop your videos and adjust the cropping area of individual clips.
  • Your final video can be exported in any of the following aspect ratios: 3:4, 4:3, 9:16, 16:9, 1:1.
  • Video clips in the opposite orientation of the one you selected will be letterboxed or pillarboxed by default. You can change this behavior on the new Settings screen.
  • There is now an option to automatically save your video to your Photo Library when you tap the Share button.
  • You can now 3D Touch a photo or video on the video selection screen to preview it before selecting it.
  • You can now mute all of the clips at once from the music selection screen.

With this update, Snapthread becomes the best app for combining and sharing Live Photos. Personally, it has completely changed the way I think about and take Live Photos. I’m much more likely to keep a subpar photo now if the underlying video is good. And since Live Photos also capture the moment before I take the picture, I find myself mashing the shutter button while Charlie is saying something cute, knowing that I likely captured most, if not all of it.

Anyway, I hope you like the update and I’m looking forward to getting started on the iPad version in March!

Snapthread Roadmap

Landscape support is coming to Snapthread on Monday. It seems like such an obvious thing, and I’m sure anyone who hasn’t been following Snapthread’s development is wondering why on earth I didn’t support landscape videos to begin with. The truth is, this app seems to have taken on a life of its own, and has whisked me far away from the path of my original intentions. What started as an app to merge Snapchat videos is now on its way to becoming a complete video studio for Live Photos.

I didn’t anticipate that, but I’m excited. Really excited. To me, Snapthread 1.5 is really Snapthread 1.0. The beginning of a new app.

I have so many ideas for the future, but for the next point release I’m waffling between these two priorities: revamping the title card system, and making the app universal.

Currently, title cards are extremely boring and limited. However, they’re also not an essential feature, and the app still does something really useful without them. So, I’m leaning towards focusing on the iPad version for the time being. I’m also really hoping that I’ll generate enough revenue over the next few months to hire a designer to help me with some fun backgrounds for titles. Perhaps making the app universal would also boost sales and help fund that.

Anyway, here’s a list of features I think might be cool additions to Snapthread:

Planned before 2.0

  • iPad support
  • New and improved title cards (multiple title cards that can be rearranged, have fun backgrounds and fonts, etc.)
  • For the initial view for video selection to be similar to Photos’ “Moments” tab, to make it easier to find what you’re looking for

Wishlist for the future

  • Video filters
  • Stickers maybe?
  • Localization
  • Ability to select a particular time range of background music
  • A way to either manually auto-generate or perhaps have the app surprise you with a video based on a “moment” in your photo library. Similar to Photos’ “Memories” feature.

I’m committed to improving Snapthread as it’s become one of my own most frequently-used apps. I love making compilations of Live Photos and videos of Charlie to post on Instagram or send to my parents, who only get to see him in person a handful of times per year. I hope others will get as much enjoyment from it as I do, and will consider it $2 well spent.

I think I’m going to take the month of February off from programming, and focus on blogging, taking care of myself, and spending more quality time with my family. I’m looking forward to relaxing, writing, and chatting with you all via Twitter, e-mail, or Micro.blog.

My iPad Wishlist

Last month, I wrote about why my current MacBook Pro may be my last Mac. To summarize: even though I love the Mac, I really enjoy using iOS and am betting that in 3-4 years, when I’m ready to upgrade my computer, the new model of iPad Pro will be able to fit all of my computing needs. Yesterday, Ryan Christoffel over at MacStories wrote a post entitled “What I Wish the iPad Would Gain from the Mac.” He had some good ideas; I particularly agreed with his requests for multiple instances of the same app and persistent background privileges for apps. Here are some other things on my iPad wishlist:

Time Machine backups

Cloud backups are great and all, but who wants to put all their eggs in one basket? I sure don’t. That’s why I’d like to be able to backup my iPad by connecting it directly to an external hard drive. Sure, you can connect an iPad to your Mac and back it up that way…but if the point is to go Macless, then the iPad needs its own independent solution for creating physical backups.

Default apps, file handling, etc.

On my Mac, I have Safari set to automatically download files to my Desktop. I’d love an option in Safari for iOS to just download all files, no matter what type they are, to some designated folder in the Files app. These downloads should be displayed in a magical pane called a “download manager,” with fancy progress bars and “time remainings” and the whole kit and caboodle. Then, from Files, I should be able to tap on a file and it will automatically open in a default app of my choosing (unless I choose a different app from a menu of available apps).

Yes, I just described exactly how that works on a Mac.

Editing a file with multiple applications on iOS feels like a game of hot potato: the file gets passed from app to app, but nobody wants to own it and God forbid it “land” anywhere. Coming from the Mac, I like my files to have a home outside any one application. Files.app attempts to achieve this, but the existence of app-specific folders confuses things. It’s as if the transition from “let’s abstract away the file system” to “okay…I guess we can show you some of the files” was never quite completed. I don’t care about accessing hidden system files or anything, I just want Apple to firmly decide what mental model they want users to have when it comes to file management on iOS, and then use the basic principles of design to clearly communicate that.

iPad-only design paradigms/UI controls

Size classes aren’t good enough. There, I said it. The iPad needs more than just UISplitViewController: it needs more UI controls that are tailor-made for it. It needs its own coherent design language that is an extension of the iPhone’s: similar in spirit, but different. All of this needs to take into account the different ways that people use an iPad: on their lap with no hardware peripherals, with a keyboard, with an Apple Pencil or other stylus, etc.

Most importantly, Apple needs to lead the way on this with its own first party pro software. I think they should start with Logic, and charge a hefty price for it. That would be helpful.

And okay, can we talk about the fact that the 12.9″ iPad Pro has a resolution of 2048 x 2732 and still only shows, what, six app icons per home screen page? (an exaggeration, I know…but good grief!)

Multi-tasking improvements

I would love the ability to have some persistent “spaces” on my iPad of some kind. In other words, a set of side-by-side apps that always remained a pair no matter what. For instance, I’m imagining a space labeled “podcasting” that showed a recording app, a chat room app, and a slide-over with notes, or something. An app would be able to be associated with multiple spaces. I think this approach would fit a lot better with the way most people work.

Xcode, but probably not Xcode exactly

The last thing I really need in order to live the iPad Life is a way to develop apps on it. With wireless debugging now a reality, and a rumored API that would bring some cohesiveness to Mac and iOS development (I’m betting that’ll be Swift-only), a full-fledged IDE for iPad seems more possible and more likely than ever. I doubt it’ll support Objective C, and it’ll probably push Storyboards more than ever, and I’ll love it so so much.

Anyway, I’m pretty sure all of these things have been mentioned by other people a zillion times, but they’re also the things that are most important to me, personally. And that’s why you read this, right?

Snapthread 1.5 Beta Test

I’m going to do something I’ve never done before: ask people to beta test my app! If you’re interested in being a part of my very first beta test, please either send an email to feedback@beckyhansmeyer.com or DM me on Twitter (@bhansmeyer). All I need to know is what email address you’d like me to send a TestFlight invite to.

I’m hoping to have a build ready for testing sometime this weekend. In the meantime, here’s some more info about this version of Snapthread!

What’s New in Snapthread 1.5 (Build 26…probably):

  • New icon and slightly tweaked design
  • Support for landscape Live Photos and videos
  • Now you can change your final video’s aspect ratio  to any one of the following: 4:3, 3:4, 16:9, 9:16, 1:1 (and you can switch between them and preview them on the fly)
  • A new settings screen allows you to turn on auto-saving (which saves your video automatically when you hit “Export”) and letterboxing
  • Trim videos

What Still Needs Work

  • If you’ve already trimmed a video and go back to change it, the trimming handles don’t reflect your previous trimmed portion.
  • You can’t adjust the crop rectangle of a video yet. So if you select a 1:1 ratio, important things will probably be cut off.

I’m really looking forward to getting version 1.5 out in the world, but I want to make sure I get some of the kinks worked out first. Thanks in advance to all my beta testers!

My Last Mac

‘Tis the season for End of the Year blog posts! Much like Charles Dickens’ three Christmas ghosts, the blogosphere is frequented by holiday posts, some reflecting on the past, some making sense of the present, and some speculating about or making resolutions for the future. With a fresh update to Snapthread packaged up and sent to the review queue, I thought I’d sit down and write a little something about the Mac: specifically, why my current Mac may be my last.

Quite an incendiary statement, isn’t it? If you’re heavily involved in the Mac community, it can evoke strong emotions: defensiveness, sadness, nostalgia, or perhaps hearty agreement. If you’ve read my blog for awhile, it might also elicit confusion. “Wait, Becky. I thought you loved your new MacBook Pro?” I do love it! It’s a great little machine. I love the Touch Bar, and the big trackpad, and the beautiful screen. It’s fast, and the few keyboard issues I’ve had have quickly resolved themselves. I love the Mac, and I hope it has a long, prosperous future ahead of it.

Here’s the thing, though. I replace my computer every five years. Five years is an incredibly long upgrade cycle in the world of technology. This post isn’t about the quality of the Mac declining, but rather the quality of iOS improving. I’m making a bet that by the time I’m ready to buy a new computer, the iPad Pro is going to be able to do everything that I need it to do, including run Xcode. And if there’s a few little things that it still can’t do, I’m betting this 2016 MacBook Pro will still be chugging along in 2021.

I mean, think of the changes that have come to iPads between iOS 6 and iOS 11. Now imagine what changes could occur between iOS 11 and iOS 16 (or whatever it’ll be called at that point). Multitasking will continue to improve, and maybe there will be some kind of panel/windowing system. Hopefully it will be easier to shuffle files between apps. There will likely be hardware keyboard improvements and perhaps even an extra port or two. There will be even more pro software from great folks like Affinity.

In short, I’m feeling really optimistic about the future of iOS, despite the many hiccups I and others have experienced with iOS 11. And I never thought I’d say this, but I’m looking forward to living the iPad lifestyle. Just not yet.

Why switch at all? Well, first, it would be a great relief for my bank account. Replacing a Mac, Apple Watch, iPad, and iPhone on a semi-regular basis gets really expensive (as those of you shelling out for an iMac Pro today can painfully attest). Taking one of those devices out of the mix can help a lot. Aside from that, there are four main reasons why I’d like to move to an iPad someday: 1) cellular connectivity, 2) detachable keyboard, 3) Apple Pencil support, and 4) overall portability.

Maybe next I’ll write up my grand wishlist for my “ultimate” iPad Pro. ?

Staying Focused with an App Mission Statement

One important part of marketing an app is developing an elevator pitch (for more info on that, see Aleen’s great post at App Launch Map). An elevator pitch helps you tell others what your app does and why it should exist without going into too much detail about its entire feature set.

A mission statement (also called a vision statement/statement of purpose) is slightly different. It can also be used for external marketing; however, it’s primary purpose is to provide internal guidance. A company’s mission statement should ideally be consulted before making any product decisions, codifying any policies, or beginning any strategic initiatives. It describes the company’s “core” and helps prevent a loss of focus.

I think we can all think of at least one app or tech company that seems to have lost its focus lately (?? Dropbox). iTunes used to be about music. VSCO used to be a great photo editor. Everything Facebook owns now has Stories inside of Stories. Indeed, feature creep and a general misunderstanding of user wants/needs has ruined many a good app/service.

That’s why I decided to come up with a mission statement for my app. As I’ve been working to improve Snapthread (yes, I decided to make the “T” lowercase; it’ll be reflected in the next update), I’ve found myself getting lots of ideas for new features. I want to make sure I don’t stray away from the app’s true mission.

So here goes: Snapthread’s mission is to provide the fastest, most intuitive way for people to merge Live Photos and videos for the purpose of compiling and sharing their memories.

I like that this statement has a human component. If I’m going to be returning to this over and over, I want to be reminded that my primary goal is to improve people’s lives (if only in a small way). It also brings accessibility to mind. From this, you can see that my goals are to be fast, intuitive, and to focus on video merging.

How is this useful in practice? Like this: if ever I get an idea for a feature that seems cool, but would greatly increase video export times, I’ll toss the idea because my goal is to be fast. If I ever find myself adding a lot of complexity to the interface, I’ll have to take a step back and ask myself, “Does this slow people down? Does it make the app less intuitive? How does this affect the user’s workflow?” Another example: I’m planning to make Snapthread a universal app. I’ll probably do a lot with drag and drop, because dragging and dropping things on an iPad is both fast and intuitive.

My mission statement also reminds me of how my app is different from others, lest I be tempted to copy them. For instance, Clips also lets users merge videos. However, it doesn’t support Live Photos and is focused more on all of the fun effects that you can add to your movies. It also allows project saving, which adds a data persistence layer and a lot of added complexity. Snapthread doesn’t save anything, because it’s meant for quick creations without a lot of “tinkering.”

An app mission statement doesn’t have to be super formal. It doesn’t even have to be a statement…it could just be a few bullet points (I’d say no more than five). For me, it’s just one more thing to help me focus, especially when I’m trying to make to-do lists and wondering which feature I should tackle next!

SnapThread 1.1 with Live Photo Support

I have a confession to make: I released SnapThread too early. I thought it was a good MVP (minimum viable product), but I was wrong. It was a little too buggy, and didn’t have a real “killer” feature.

The good news is, SnapThread 1.1 is now available, and it’s what I should have waited to release in the first place. I’m hoping that with the addition of Live Photo support, SnapThread can now be people’s go-to app for quick, easy portrait video compilations.

New features:

  • Live Photo support! SnapThread will strip the 3 second videos from your Live Photos and allows you to stitch them together.
  • The app now presents the native iOS share sheet upon successful export.
  • New duration limits. Filter your photo library by videos under 10, 15, 30, or 60 seconds.

Improvements/Bug fixes:

  • Faster exporting, and fixed a bug where the exporting would fail when trying to merge over 16 videos at once.
  • Better progress reporting. Downloading lots of videos from iCloud can take awhile, and now the app more accurately reflects the download’s current progress.
  • Smart aspect ratio: since Live Photos are 3:4 and regular videos are 9:16, SnapThread chooses the final video’s aspect ratio based on what you have more of. So if you have 45 Live Photos and 1 video you want to merge, the final video will be 3:4. Likewise, if you have lots of widescreen videos and only a few Live Photos, the final video will be 9:16. (you should see the tangled if-else statements that determine the video clips’ scaling and translation values…it’s terrifying).

Since “the proof of the pudding is in the eating,” here’s a video of Charlie’s day at the pumpkin patch that I stitched together from Live Photos (and one video):

Future plans/ideas for the app:

  • Photo library album picker (so you can find clips more easily)
  • Scaling improvements and fixes (I’m sure there’s some edge cases I missed!!
  • Ability to mute individual clips?
  • Ability to add a very simple title to beginning of video?
  • New localizations
  • Accessibility improvements
  • iPad version??

SnapThread Now Available

SnapThread icon

My new app, SnapThread, is now available on the App Store! SnapThread is a simple, no-frills utility for merging portrait videos from apps like Snapchat and Instagram Stories.

I am hoping to add support for Live Photos in the next version. In the future, I may also add the ability to include a title for a few seconds at the beginning of the video, or add a single background music track. However, I don’t want to complicate the app too much, so those features aren’t guaranteed to make the cut.

Let me know if you run into any trouble (errors and such) using the app, and if you like it, please consider leaving a rating or review. Thanks!

Please, Don’t Write About My App

Please, don’t write about my app. It’s not that good. In fact, it probably crashes sometimes. Also, I don’t really know what I’m doing.

Please, don’t tell your friends about my app. They probably won’t like it. I mean, the art assets aren’t good enough. It’s too simple. And it only really appeals to a tiny niche anyway.

Thus goes my inner monologue every time I prepare to ship an app. It’s not because I’m humble: trust me, I’m not. It’s just…fear of failure, I guess?

For indie developers, marketing is especially important. You gotta get the word out about your stuff. You gotta build your audience, refine your #brand, hack all dat growth, and so on and so forth. It feels gross. It isn’t, though—at least not for the most part. I struggle with it though, as I’m sure many of you do as well.

Look, my app isn’t special. It’s not Apple Design Award material. Does that mean it shouldn’t exist? No, it doesn’t mean that at all. I created something that’s useful to me, and now I’m going to share it with others. If they don’t find it useful, that’s fine. But if I want to give it its best chance at success, it’s still my job to tell its story.

But if you do…

Look, if you’re going to write about my app, say this: it’s a simple utility for merging short, portrait videos. It’s called SnapThread. It’s currently waiting for review.

It’s for parents who have a bajillion Snapchat videos of their kids with Marilyn Monroe hair or with a hot dog dancing on their head or what-have-you and all they want to do is create a sweet supercut of them all. No fancy filters or overlays or stickers or cropping. No dumb letter-boxing that forces it into landscape. Just stitch ’em all together and get on with your day.

It’s for travelers who have 30 Instagram Stories videos from their trip to Disney World spread over several days, and want to mash them all into one movie.

It was created by a mom who wanted to visualize how her son has grown.

SnapThread does what it says on the tin: it let’s you select portrait videos from your photo library that are 15 seconds or less, re-arrange them to your liking, merge them together, and save them to your photo library. Sometimes it takes a long time. Sometimes the videos have to be downloaded from iCloud. Sometimes their rotation has to be fixed before the merge can finish.

This isn’t an app for your home screen. This is an app you throw in your “Photo/Video Editing” folder and use once in awhile when you need it. It’s like “Clips,” but simpler.

SnapThread will be out soon. In the meantime, you can check out this page about it (the App Store link doesn’t work yet obviously).

Tell your friends! Or don’t, maybe. I don’t know.

Too Many AVPlayers?

Wow, I can’t believe it’s nearly September! For me that means I’m 1) popping allergy pills like a maniac because UGH RAGWEED, 2) getting really excited for the September Apple event, and 3) scrambling to finish up a random side-project app before iOS 11 hits the mainstream.

A couple nights ago I ran into a strange bug with my app, which uses AVFoundation to merge videos. Sometimes I would be able to export the final video with AVAssetExportSession and save it to my photo library, and sometimes it would randomly fail with the following error:

AVFoundationErrorDomain Code=-11839 "Cannot Decode" and NSLocalizedFailureReason=The decoder required for this media is busy., NSLocalizedRecoverySuggestion=Stop any other actions that decode media and try again., NSLocalizedDescription=Cannot Decode

In my app, every time a new video clip is added to the list of videos to be merged, I re-generate a preview of the final merged video. After merging the video, I set up an AVPlayer with the AVComposition like so:

func setupPlayerView(playerItem: AVPlayerItem?) {
        guard self.player == nil && playerItem != nil else { return }
        
        // Create an AVPlayer and AVPlayerLayer with the AVPlayerItem.
        self.player = AVPlayer(playerItem: playerItem)
        let playerLayer = AVPlayerLayer(player: player)
        
        // Configure the AVPlayerLayer and add it to the view.
        playerLayer.videoGravity = AVLayerVideoGravity.resizeAspect
        playerLayer.frame = (self.videoPreviewView?.bounds)!
        self.videoPreviewView?.layer.addSublayer(playerLayer)
        
        ...
}

I always made sure to set the AVPlayer to nil before re-generating the preview, so I couldn’t figure out why there would be any other “actions that decode media.” A trip to Stack Overflow revealed a possible platform limitation on the number of video “render pipelines” shared between apps on the device. It turns out that setting the AVPlayer to nil does not free up a playback pipeline and that it is actually the association of a playerItem with a player that creates the pipeline in the first place. Since developers don’t seem to have any control over when these resources are released, I knew I’d have to figure out another solution.

In the end, I decided to initialize the view controller’s AVPlayer right off the bat with its playerItem set to nil. Then I changed my setup function like so:

        // Create an AVPlayer and AVPlayerLayer with the AVPlayerItem.
        self.player?.replaceCurrentItem(with: playerItem)
        let playerLayer = AVPlayerLayer(player: player)

Replacing the player’s playerItem instead of initializing it with a new playerItem each time (even though the player was previously set to nil), seems to prevent that weird “cannot decode” error (so far, at least). I’d like to know more about this error and why exactly it occurs, just out of nerdy curiosity.

Anyway, I hope this helps somebody out!

Data Persistence Dilemma

Sometimes, in order to solve a problem, I have to think through it out loud (or in this case, in writing).

Here’s the sitch: I’m making an app for knitters and crocheters. They need to be able to manage projects (i.e. “Baby blanket,” “Socks for mom,” etc.). In addition to a bunch of metadata about each project, users should be able to add photos and designate one or more images or PDF files as the project’s pattern. A PDF or image of the pattern isn’t required, but including one will allow users to enter a split view where they can view the pattern and operate a row counter at the same time.

A project shouldn’t necessarily “own” its pattern. In other words, a pattern can have multiple projects associated with it (say you want to make the same baby blanket for multiple babies), so as to avoid the needless duplication of the pattern file. A pattern can exist without a project and a project can exist without a pattern, but when linked, the project becomes the child of the pattern.

My user base includes people who may not always have an internet connection. Therefore, all data needs to be stored locally. However, those who do have an internet connection are going to want iCloud sync between devices.

I like Core Data. If I were to set this up in Core Data, without any consideration of iCloud syncing, I’d create Project and Pattern entities, store images and PDFs in the file system, and call it a day.

iCloud syncing is where things get murky for me. Core Data + iCloud is deprecated, and I don’t want to use it. Not only that, I don’t know what to do with the PDFs and images. Storing them as BLOBs in Core Data seems like a bad idea. I understand how to save them to the file system but don’t understand how to sync them via iCloud and also have a reference to them in Core Data. Do I use iCloud Document Storage for them? Do I zip them up somehow (NSFileWrapper??) and use UIDocument? How do I store a reference to them in Core Data (just the file name of the UIDocument, since the file URL is variable?). If users will be adding photos and PDFs at different times, do I use one UIDocument subclass for photos and one for PDFs or do I use a single document and update it with the added information? You can tell I obviously have no idea how this works, and a multitude of Google searches has yet to clear it up for me.

As for the rest of the information in Core Data, I’m thinking of trying to sync it  with CloudKit using something like the open source version of Ensembles or Seam3.

I guess I’m not sure if I’m on the right track and would welcome any advice/feedback. I’d really like to stay away from non-Apple services (like Realm) for the time being. Comments are open!

WWDC 2017: Designing for Everyone

If I had to guess at an unofficial theme for this year’s WWDC, it would be “Designing for Everyone.” In addition to being the name of an actual session (806: Design for Everyone), the phrase captures the main thrust of what many of the other sessions were about as well. More than one presenter mentioned that while accessibility wasn’t a primary focus when re-designing some of Apple’s first party apps for iOS 10, it became a priority for iOS 11. One presenter (I can’t remember who) admitted that her team still had plenty of work to do on the accessibility front.

The session 802: Essential Design Principles reminded me of the best book I read in grad school: Donald Norman’s The Design of Everyday Things. Apple Design Evangelism Manager Mike Stern outlined many of the same principles that Norman discussed in his book—things like natural mapping and affordances.

In Chapter 2 of The Design of Everyday Things, there’s a little box with questions that designers should ask about their design:

How easily can one:

  • determine the function of the device [or in our case, an app or feature]?
  • tell what actions are possible?
  • tell if the system is in desired state?
  • determine mapping from intention to physical movement?
  • determine mapping from system state to interpretation?
  • perform the action?
  • tell what state the system is in?

(Norman, D. A. (2013). The design of everyday things. New York: Basic Books, a member of the Perseus Books Group.)

The questions are based on seven stages that humans go through when taking an action. When people use our apps, they have a goal in mind that they want to accomplish. They should be able to figure out what actions are available, which ones will lead them to their goal, and how to execute said action(s). Ideally, they should be able to do this without any additional walkthroughs, on-boarding, or tooltips.

They should also be able to accurately predict and evaluate the outcome of their actions. This can be achieved using things like error/success messages, animations, button state changes, view transitions, etc.

An app’s design should clearly communicate what you can do with it. Can you toggle a switch? Press a button? Scroll up and down? All of those things are called “affordances”—things the app allows you to do. 3D Touch is tricky because one of the affordances of a flat piece of glass is NOT that you should be able to exert pressure downward “into” it. Rather, glass, as a material, affords swiping and tapping by its very smooth, flat nature.

AirPods are another example of hidden affordances. Can you tell by their design that you can tap on them to execute additional functions? No. That’s traditionally considered bad design.

State changes are also important. What state is your app in? Is it syncing, or loading something? If you are using a tabbed interface, is it clear which tab the user is currently viewing? These questions are integral to making sure your design is accessible for everyone.

I’m planning to spend the next few weeks updating Nebraska93’s design to be compatible with Dynamic Type. A few days ago I tweeted a video of my successfully re-designed table view cells and I’m really surprised by the amount of favorites and retweets it got. A few people remarked that they didn’t know Accessibility Inspector could adjust Dynamic Type settings on the fly.

My advice to fellow devs is twofold. First, open up Accessibility Inspector and see how your app looks to people who have low vision. Off-hand, I can think of three people that I know in real life who use the larger text size settings, and I suspect it might be way more common than you might think. Second, read The Design of Everyday Things. It’ll make you really mad at a lot of doors and household appliances, but it’s worth it!