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:
- User taps on one or more videos and taps the “done” button
- 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.”
- 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:
- a thumbnail representation of itself
- 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!