Recently, I’ve been discussing ways to architect iOS applications to make them easier to test. Yesterday, I stumbled upon this talk from WWDC ‘17. In this video, the presenter espouses a lot of the same ideas I’ve been advocating here. It’s a great video and I highly recommend it.
Photo by Anton Darius | @theSollers on Unsplash
Lately I’ve been learning UI design basics and spending time on Dribbble, a site where designer types show off their latest creations. My first thought when I see an amazing animation is always ‘Whoa, that looks so cool!’ and my second thought is always ‘Whoa, I have no idea how to implement that!’. Studying these animations has inspired me to close the gap between what designers are creating in After Effects and what I’m able to do with UIKit.
In order to hone my skills and challenge myself, I decided to take a design from Dribbble and implement it in Swift. I chose something that wasn’t too complicated and had a variety of animations. The one I chose was the VNPAY concept design by Ramotion. Ramotion does amazing work and they’re SF locals!
This app concept is a simple 2 screen interaction. It contains a login view which transitions to a dashboard screen. It utilizes a Google Material Design aesthetic, in which interactive controls appear to float above the rest of the UI. I particularly like the animated blue stripe on the login screen so this is what I implemented first.
I admit that I picked this interaction partially because I wanted to learn how to use Lottie and I thought the stripe animation would be a good first experience. I was seriously impressed. Briefly, Lottie enables exporting vector based animations from After Effects into iOS or Android. This means you have all the power of AE animations in your iOS projects. Learning After Effects and setting up animation exporting consumed almost half the time I spent on this project but it was worth it. My blue stripe doesn’t do justice to Lottie’s power. Head on over to their site to see some of Lottie’s amazing abilities (but not yet!).
To the left you can see my implementation. For the rounded controls and buttons, initially I had integrated material-components-ios. This is Google’s implementation of Material Design for UIKit and is a rather large library. I could imagine using it if I was going all in on Material Design. For this project, however, it seemed a little heavy handed as I only needed a few shadows and rounded corners. In the end, I ended up dropping it and rolling my own components.
Next, to implement the actual animations, I tried Stellar. I had high hopes for this library — It was well documented, had a nice interface and seemed quite powerful. Unfortunately, I struggled to integrate it with my project, the maintainer had stopped supporting it a few Swifts ago. Additionally, it was difficult to make simple animations work properly and, most importantly, it didn’t take advantage of the more modern UIViewPropertyAnimator API which I was interested in learning.
Eventually I ended up dropping Stellar and creating my own animation library. Né Disco. Disco is a thin wrapper around UIViewPropertyAnimator. It simply adds a fluent interface to property animator. It’s pretty bare bones at the moment but I intend to flesh it out when I have some time.
Since we’re on the topic of libraries I created for this project, I’d also like to introduce Choreo. Choreo doesn’t do any animation on its own. It simply choreographs the animations between several views. Users of the library can specify the amount of time the entire animation should take, the start and duration time of each view’s animation. Choreo will start each view’s animation at the proper time. Like Disco, I intend to spend more time polishing this up in the future.
Some challenges I encountered during this project were getting the animation timing functions to match the gif. I broke their gif down into individual frames to calculate the length of a each animation but had to guess at their timing curves. I also never figured out exactly what typeface they are using.
This ended up being a really fun project. I learned a lot about CoreAnimation and UIViewPropertyAnimator and got two new libraries out of it! In the future I intend to do another one of these little experiments, but for now I’m switching gears and am attempting build my daughter some sort of electronic toy. Wish me luck!
I'm a freelance iOS developer based in San Francisco. Feel free to contact me.
In my last article, I discuss the easiest path to testable Swift. In that article I list qualities that make tests valuable. Additionally, I show that business and application logic should be decoupled from volatile or asynchronous dependencies. Now I’d like to focus on the “State” object that houses all of this logic and illustrate some design decisions that will make it easier to test.
An experienced tester knows that certain features are trivial to test while others must be mangled and distorted before they yield to testing. Tests that are easy to write are ones that require little or no arrangement code, don’t require new classes to enable testing (ie. mocks or stubs) and produce easily verifiable output. The easiest thing in the world to test is a pure function:
In my last article I touched on a few ideas to make Swift testable. Here I’d like to demonstrate these ideas by implementing a hypothetical feature. The feature is written using TDD and exhibits these virtuous patterns. Before I go on, I’d like to describe the attributes which make a test good.
Enlightenment is intimacy with all things. —Ehei Dogen (1200-1253)
I’m coming clean. I’m embarrassed to admit it, but I’ve been a professional software developer for twelve years and have hardly written any tests. I’ve embraced the unit testing cult a few times, but every time I did, I spent more time hacking my code to make it testable than writing new features. My velocity went into the toilet, my once beautiful code became riddled with concessions to make it testable, tests would break after small changes, and worst of all, they never seemed to surface any genuine defects. I would eventually give up with the excuse that “iOS code isn’t testable” or “unit tests are for people who write bad code”. Such hubris!
In my last post I explained some of the common anti-patterns that developers fall into. In this article I’d like to explore some architectural principles that help make code more robust and extensible. Like all ‘rules’ in software development, these are really only guidelines, so if something feels awkward or forced, it probably is.
Being a freelance iOS developer, I get the opportunity to work on a variety of projects, written by developers with varying degrees of experience. This has given me the opportunity to catalog the most common iOS anti patterns or ‘Code smells’ I’ve smelt. I will enumerate the most common smells and some possible solutions to guide you on your path to mobile app nirvana.
Developers, repeat after me, “My app is not a web page”. Again! “My app is not a wep page”. It seems that most developers are writing their mobile apps like they did web pages in the 1990’s. They makes requests to the server, put the app into a waiting state, and display the response in the UI. If they are offline, an error is reported to the user and the app is unusable. This experience is fine for a webapp in the browser with little or no local storage and a ubiquitous network connection, but falls short in the mobile world.
In my previous post I taught you how to wrangle your game initialization code in order to keep it from breaking with every refactor. Today, I’d like to talk about event handling and how to get a handle on it (pun intended). If you’re anything like me, your event handling code (generally your touchesEnded:withEvent:) is the longest method in your whole application; littered with switch statements, if/else clauses and enough boolean flags to make George Boole turn over in his grave.
Writing games is hard. Writing games for iOS is even harder. Typically, one of the most fragile and error prone parts of a game is the loading and initialization process. For obvious reasons, it is also one of the most critical pieces of your app. By using a sequencer, developers can define dependencies for steps in their loading process thereby removing some of the brittleness and instability from their game.