A Christmas Challenge — A Cinema app in just 7 days
When you have a break from work, what do you do with your extra time? Spend it with family? friends? Yoga in a log cabin?
Well, I like to have a bit of fun with programming. This Christmas I saw an interesting concept for a Cinema app. Within a week, I crafted design from free UI kits and made app functionality. I found APIs of real cinema apps for getting information to show. Day by day I was adding features and learning more about Moya, PromiseKit, JSON decoding, animation libraries.
Follow me on a journey of how this Christmas I built a Cinema app and how I think you could too!
The catch? You have just 7 days to do it.
This was a learning project for myself, the primary goal was to build a prototype as quickly as possible. My approach may not be the best, but it was quick, it works, and most importantly I learned from it.
Creating a Starting Point
Now my skills are definitely not as a designer. So I knew it was not feasible to design and develop this app concept within the allocated week.
This is where I like to create a mood board (which is really just a nice way of saying, I gathered a tonne of designs inspiration from Dribbble, Pinterest and Behance). In fact, the mood board for this prototype ended up being just short of 1GB and contained 44 separate designs!
A lot of love and credit goes to Mark Fletcher for the Kino Movie Kit where the majority of my app design came from.
The other important element was the data to drive the app.
Now this is optional as you are able to use static JSON files on your computer, or just use static values in the app. For me, seeing the app updated with live information each day added a lot to the product and made it really fun!
In order to identify the requests, I needed to use an app on my phone called Charles Proxy. It allows you to see the network requests your phone is making. I used the official ODEON application as per normal, and started to see the requests it was making! I could then make the same requests in my app, to get the data necessary to display!
I did, however, notice that I wasn’t getting as much information as my designs were showing. For example, I had a design for Cast and Crew but this information was not available to me from the ODEON APIs. In this case, I knew that other public APIs existed such as TheMovieDB which had this information.
So in your own quick projects, I recommend getting a number of designs that really inspire you and build a vision in your mind. It doesn’t need to be for a cinema app but for anything!
You also need to find APIs or create static JSON files which align with the information you want to show in the app.
I’ve already spoken about the need for data to drive your application. But it’s also going to be difficult to build every aspect of your project from scratch.
Sure you can build your own networking, image caching, visual elements etc — but if you’ve done these before then it can become an unnecessary step which prevents you from being able to do other enjoyable things!
Some dependencies will likely just come as you’re progressing — for example, I added “GSKStretchyHeaderView” as a dependency once I got to the point I wanted a stretchy header in my lists.
If you try this for yourself, why not use a library you’ve never used before? I decided to use PromiseKit a couple days in having never used it before — and now I’m learning all sorts about it!
Now for the implementation itself, this is just following the steps that I went through and the order I chose to tackle the problems:
Day One (Tweet)
So in this particular app, I knew the main component was going to be the detailed movie view which contained all the information about the particular film. I wanted to get this formed first as it was a requirement for a lot of other views!
I created a very simple UITableView which converted a list of items (in a separate class) into a cell view. At this point, each view was hardcoded and wasn’t even fully styled.
This gave me the foundation to start working on the design part of this view. I went through each of the XIBs one view at a time and styled it as per the designs I had. It began to look like a thing!
The next step was to use Moya and follow their basic documentation to get a ODEON “provider” created. This enabled me to make a network request to load movie details for a hardcoded movie. You’ll notice for the first days of the project I was actually using the exact same film because it was hardcoded!
Once I had the networking being fetched I was able to pass that information into the “structure mapper” above. I then started to pass view models into each of the items which could be used to replace the hardcoded data in the views with a value actually in the data.
Day Two (Tweet)
While I knew the work I did on day one wasn’t complete, it was important to keep the momentum going. So I moved onto the next view — in this case I chose to do the show selection view as this was the next step in the ticket purchase flow.
The main difficulties with this page was the use of a vertical UICollectionView for the grid, inside of a horizontally scrolling container for the individual days. I also needed the ability to change the screening type which updates all of the showings!
Going back to what I said earlier about choosing your battles and allowing the use of dependencies to save time in favour of not repeating past learnings. In this case, I chose to use XLPagerTabStrip to provide the horizontally scrolling interface and the individual day labels. I also took advantage of ContextMenu to provide an easy dropdown mechanism to change the screening type.
These were two libraries that, while I knew how to achieve the functionality they produced, I had never actually used directly. I can say now that both of them were extremely easy and intuitive to implement which was fantastic!
Day Three (Tweet)
On the third day, which just happened to also be Christmas, I decided to tackle the seat chooser interface. Now this was actually something I was quite looking forward to! I had the most designs looking at how it would work but really didn’t turn out the best in my own opinion.
The data I was receiving to construct this view was fairly difficult to work with for a start so it took longer than expected to do the JSON decoding. The solution itself wasn’t particularly bad but it took a lot of investigation to work out what each value in the data was for.
I also had to create my own UICollectionViewLayout which was not something I was super familiar with. In order to achieve my view I converted the JSON data into a single array of all the seats and then converted the seat’s absolute positional information to simply be the row/column it sits within. This meant I could easily multiply the seat’s position by the seat width/height to get the new absolute position.
This system does work for most of the cases I tested it within. But on smaller screens (because I attempted to fill as much of the space as possible) not everything could fit. This problem is likely exasperated on smaller screens.
In the future, I’d like to address this by enabling zooming and a more intelligent sizing mechanism which centers seats on the first draw.
Day Five (Tweet)
The astute will have noticed I missed day four and this was simply because very little looked good at the end of it. I had set myself the intention of having one “list view” and having different “structure mappers” for each view which would let the contents of it be changed.
However, once I got to the home screen I started seeing a couple of issues with the specific way I had implemented it so needed to do some cleanup.
This was also the first point in the project where I started having to create a UITabBarController with separate pages for home and settings! (There’s also a third members tab that has nothing in it)
By the end of day five, I had some very simple horizontal scrollers on the main home screen as well as a cinema selection mechanism in the settings page. This wasn’t fully wired up though and it was still hardcoded to a single cinema.
Day Six (Tweet)
So today was the final day I was going to be developing on the project and set the goal of adding more information to the home screen as well as introducing cast profile pages.
Luckily as I had made the list views so flexible it was a breeze to add cast profiles as soon as I had the networking added to the Moya provider I created earlier. It’s beautiful when a plan comes together.
The rest was pure beautification and linking all of the components together including allowing tapping on films in the home screen to open a film, changing your cinema selection would change the show information, etc.
While it’s pretty awesome to see something come together so quickly, the important part of this exercise is to learn something new out of it.
Moya — Through this project I’ve really liked the abstraction and simplicity this library adds to networking. It allowed me to neatly separate the different APIs I was dealing with. You can also find a good guide on Moya here.
PromiseKit — I decided to add this library later on in the project to add an extra challenge but I found it extremely valuable especially when used with Moya. I had to create an extension to do the bridging but then it made it extremely simple to chain or wait for multiple network requests to finish before carrying out an action. I definitely want to do more with this library moving forward.
Debugging — One of the main difficulties I was having was debugging some of the issues I was facing especially with the errors being thrown. I learned a valuable lesson using LocalizedError in order to give errors descriptive messages which made it easier to know what failed later on.
Speed is difficult — While I’m definitely happy with the amount of work I managed to do, the quality is definitely lacking. It’s important to highlight that throwing code together is good for experimentation, learning new things, prototyping concepts, etc but when it comes to writing production code you should definitely change priorities and think more about what you’re writing and its impact.
Ultimately I’m really happy with what I was able to achieve within a week. Not only is it functional, but I had a lot of fun doing it!
I’d love to hear about any experiences or plans you may have about a similar journey as well as what you may have learned from this?
I’d also like to see what you may do differently to achieve a better result in the same timeframe.
I’m now looking forward to the next holiday, what should I try next?
I have made the entire source code for this week-long app concept public on my GitHub below.