First steps into Rx

12. December 2017 Reactive Programming 0

When we started building a new app 2 years ago we thought we were pretty cool and hip. We started from scratch with a swift-only codebase and used libraries that had proven to be stable and well-supported. There is one practise we did not adopt: Reactive Programming. At the time it felt a bit new and scary and honestly we just couldn’t find a good reason to use it in our app. Why would we use this new way of programming that all our developers (and future developers) would have to learn?

Fast-forward 2 years later and reactive programming is everywhere. Every applicant at our company knows at least a little bit about it and you cannot visit a conference without someone talking about it. So it seemed like the right time to investigate it further and see if I could find a nice use-case for it in our App.

Starting Small

When adopting a new technology or a new library I like to do a very minimal implementation at first. I look for a use case that is ideal for that specific technology. For instance when we started using Realm I first implemented it for storing a simple list of data that had to be easily retrieved. The list was tiny and I could have used any other method of storing it (like serialising it to disk) but I knew that by introducing Realm to our codebase we would have the option of storing other, more complicated data later on.

For my first adventure in Rx I chose a similar simple use case. Autocomplete. We have a search field in our app that autocompletes city names or addresses while typing. This is something Rx excels at: taking a changing stream of data, typed text in the textfield and transforming it into something else: a list of autocomplete suggestion. Additionally, most Rx libraries have helper functions that can improve the user experience of such features even more.

The minimal implementation

First of all, I started by subscribing to any changes in the value of the “text” of the textfield.

This works as you would expect. The user types something in the textfield and the value is passed along to the “subscribe” closure that will then trigger the autocomplete logic. I won’t get too much into this logic since it is not Rx related, I chose to do all the network calls the “old-fashioned” way to keep this change as small as possible.

Bells and Whistles

In reality though, there are a few situations that you would also like to handle in this block of code to improve the user experience:

  • skip(1)
    When you subscribe to events of the textfield, the initial value of the field will also be processed. In our app we prefer not to show the autocomplete list immediately but to first show the user his or her’s previously searched locations. skip(1) makes sure the first value of the field is ignored.
  • debounce(0.3, scheduler: MainScheduler.instance)
    Since this feature is triggered by user input on a keyboard that then triggers a network call (to get the autocomplete options) we are careful about not doing these calls too often. If the user would type really fast, each change in the textfield would trigger a network call when in fact we only really care about the last change in the value. debounce(…) create a time window that cancels previous calls within that window.
  • distinctUntilChanged()
    Finally, we only really care about actual changes in the value of the textfield. A user could potentially type a value, then delete the final letter and quickly add the same letter back. The result would be a network call that would get the same autocomplete values that we already have on the screen. distinctUntilChanged() makes sure all values that are autocompleted are unique from call to call.

Summary

My tips for starting with Rx: Find a use case in your app that plays to the strengths of Reactive Programming and start with a minimal implementation.

More info and references


How To Communicate Hidden Gestures in Mobile Apps

09. January 2017 blog 0

Nick Babich wrote a nice article about different ways of teaching gestures to the users of your Apps. Communicating non-obvious usage of an application is always difficult and many times results in long, tutorial-style launchscreens in apps. Nick makes a good case for ditching these kinds of methods and instead educating your users on-the-fly with inline hints.

If you have to give your app an instruction manual, then you’re not doing a good job of communicating with your users because users cannot be expected to read a manual before using your app.

Read the full article here: http://babich.biz/how-to-communicate-hidden-gestures-in-mobile-app/


Tadaa! a design test library

07. January 2017 blog 0

“Tadaa” is a tiny library I built that allos you to quickly overlay a design over a UIViewController in an app. This allows you to check margins, colors and other UI aspects against the original design of the screen.

Check it out on my GitHub page


Simple animations with UIImageView

07. January 2017 blog 0

Our website has gotten a bit make-over the last few years. We started to focus more on the visual aspects of the site. One part of that is the use of illustrations. We wanted to give our new apps the same care and attention but sometimes it is not so easy to use branding or visuals on a relatively small screen. Nevertheless, we did some small things that make a big difference and might even make our users smile a bit. An example of this is the animation we added to indicate that you have reached the bottom of our result list.

For this animation we used a simple UIImageView with 4 separate image frames of a cyclist. The frames in this imageview are animated and the imageview itself is also animated from left to right. This results in a pretty decent animation that was made within an hour or so. Not a bad investment for a little fun!

Here’s the relevant code to animate the frames:

Download the complete Xcode playground here: AnimatedImageView.playground (42KB .zip file)


Low risk update tactics for Apps

05. January 2017 blog 0

Consider the following situation. You have had an App in the App Store for a few years and it is used by quite some people. At some point you decide to rebuild the app or refactor it in a significant way. You rebuild the app, test it thoroughly and release it to your (undoubtedly super-happy) userbase.

Except.

On the first day of your release, your enormous userbase finds a terrible bug. The backlash is terrible and any credit you had with your users goes out the window.

The first part of this story is where we found ourselves 2 years ago. We were not afraid to update our app in a significant way but we were aware of the dangers of rebuilding an entire app from scratch and putting it in the hands of hundreds of thousands of users from day 1. We decided to come up with a more low-risk tactic for the development and release of our apps. Here’s how we did it (until now):

Build

While developing the app, we tried to get the app in the hands of as many people as possible, but only people we knew could handle an unstable and ever-changing product. This first alpha group consisted mostly of colleagues and family members. This was our first line of defence for any huge bugs we potentially introduced in our product. Our Apps were distributed via TestFlight and the Google Play store but were not publicly available. We tried to release as often as possible to keep our test users engaged and up-to-date on our progress.

Internal Beta

Next, we recruited a beta group of of about 200-300 real users who were excited to test our unfinished product and give feedback. This feedback was given through an in-app feedback form (powered by ZenDesk) as well as through several to-the-point questionnaires we sent via email. We added screens to our apps that made it clear which functionality should be considered “finished” and which functionality was not available yet. This was done to further manage the test user’s expectations.

External Beta

When we felt comfortable with the stability of our apps and the most basic functionality was implemented, we took the plunge and put our app in the App Store. However! We took a slightly different route than companies normally take. We decided to put our new fancy App in the store as a second app. The original app, with a lot of users, remained in the store. Our intent was to let the userbase of our new app gradually migrate to this new app and not “scare” them with an app that was not only radically different, but also not feature-complete yet. We originally called this app “<appname> beta” but when we tried to update this app (not on the original submit unfortunately 😉 we were notified by Apple that this naming was not allowed. We opted to go for “<appname> vernieuwt (renewed)”. We made sure to properly communicate in the App Store as well as in the App itself that this App was in a state of flux and that it could still contain some bugs. Also we encourage users to give us feedback or to report any problems in the app.

Migration

Migration our users in our “old” apps to the new apps was not going to be easy. Even though the original “organic” traffic to the new app was pretty steady we still wanted to encourage existing users to use our new product. We did (and still do) this by showing banners in our old apps. Because we know exactly which functionality people use in our apps through analytics we are able to target these banners only to people who do not use any functionality that is not available in the new app yet. As we add features to the new app and the two apps are more in-sync, we can target more and more users via these banners.

This is where we are now.

Release

Since we already have our new app in the store and more and more people are using it. The actual action of “releasing” changes slightly. Instead we focus on migration of users to the new app until we reach a point where we can safely “turn off” our old app and remove it from the store.

Summary

Sure, it’s nice to push a big red button and launch a new version of your app. But considering the risks of updating an app with a huge userbase, isn’t it also nice to slowly introduce these people to your new product and not scare them off?

Currently we cannot determine yet if this tactic will pay off and if it does result in a more stable, robust and user-friendly app. I will keep you updated on our progress. In the mean time, why not consider your own low-risk release tactics?


Non-nested appending of optionals to an Array

05. January 2017 blog 0

I like to prevent nested code as much as possible. In some cases though, it might not be very easy to do this. Consider the following code that adds a String to an Array:

this simple unwrapping of an optional seems trivial but wouldn’t a non-nested version look even nicer? That’s why I wrote a tiny Array extension that allow you to write it like this:

This moves the unwrapping of the optional to the append function itself. I also added a function that takes a second optional array as a parameter and a function that takes a condition which must be fulfilled before the element is added to the Array.

Here is the full code of this extension:

 


Our flavour of the MVVM design pattern

01. December 2016 blog 0

When starting the process of rebuilding our apps, we were confronted with a problem that most old, big apps have. The logic in our apps responsible for transforming raw data to something on the screen was completely contained in our ViewControllers and Views. This means that these classes were huge, hard to read and even harder to understand. This is a common issue with iOS apps that results mostly from the M(odel) (V)iew (C)ontroller design pattern that is often used.

MVVM

For our new app we decided on the MVVM (Model/View/ViewModel) design pattern as the core of our codebase. This design pattern is meant to remove the logic of an app from the View and ViewController. Instead a new entity is introduced called a ViewModel. This ViewModel describes the elements that should appear on the screen. You could consider it a code-representation of the UI. This ViewModel is then passed to a View. The View then only has to read the ViewModel and modify the UI as specified.

However, this approach still does not take into account one of the problems we had: Where should the main business logic of the app be located? The original Model should still be transformed into a ViewModel for the View to be read. We decided to tackle this problem by introducing yet another entity: a Mapper. a Mapper is a function or class that contains all the logic necessary to transform a Model into a ViewModel. These Mapper functions mostly take a Model as a parameter but they can also be made more flexible. For instance, you might need multiple kinds of Models to generate a single ViewModel or you might want to be able to specify what kind of ViewModel has to be created.

Testing

The core functionality of our app is getting data from an API and transforming this data into something the user understands. Because our business logic that transforms our data is now contained in a single Mapper class or Mapper function, testing this logic becomes extremely easy: we write unit tests that cover our Mapper classes. An added bonus is that our ViewModels are a very precise description of our UI state, which means we don’t have to write as many (slow and cumbersome) UI tests.

 


Using the Page Object Model for structured and readable UI tests

30. November 2016 blog 0

When we started rebuilding our apps, we decided to focus heavily on stability and testing. Our old app has quite a few crashes in it and we believe the only way to prevent such error-prone apps is to put a lot of emphasis on testing from the start. In Xcode 7 Apple gave developers the opportunity to easily write UI tests. These are tests that automatically run through the interface of your app to test specific screens or components.

Once we started writing these kinds of tests it became apparent that although the tools Apple gave us were very easy to use, they weren’t leading to nicely structured and easily readable tests. Take this simple 1-action test for example:

Looks simple enough right? The application opens up and we tap a button with the text “Search”. This would work well for a single test that has to tap this button. However if there are a lot of tests that use this button this hardcoded “Search” string becomes a problem. What if we decide to rename this button? All the tests would fail and we would have to spend some time to rename all the individual references to the “Search” button. It sure would be nice if there was only one reference to this button that our tests could use.
(more…)


Using AsyncDisplayKit for a smooth UI

27. March 2016 blog 0

So we’re building this awesome new app but after spending time revamping our result list we found out it just wasn’t performing well enough. We were using a UICollectionView but calculating the position of all the elements in each item in the collection was just too slow. We found out about AsyncDisplayKit (ASDK).

ASDK offers an abstraction over UIView and CALayer that allows you to perform the calculation of frames to background threads instead of the main thread. This dramatically speeds up the rendering of complex UI’s. After implementing ASDK our list is now super smooth and doesn’t lag at all.

Here are some things to take into consideration when implementing ASDK:

  • Actively maintained. The ASDK library is under very active development. It was originally built to power facebook’s Paper app and it seems mature enough to use in live projects.
  • Objective-C, not Swift. ASDK is built in Objective-C. It’s not complicated to use an Objective-C library in a Swift project but if you’re a Swift purist you might not want to do this.
  • Nodes, not Views. ASDK uses a concept called “Nodes”. Nodes are essentially UI elements and can be considered an abstraction of a View or a Layer. You use these nodes to define your UI and ASDK will asynchronously create views or layers to represent this UI.
  • LayoutSpec, not Auto Layout. Because ASDK uses Nodes to define UI elements, it doesn’t support things like Auto Layout or Constraints. Instead, ASDK uses something called a “LayoutSpec”. There are a number of different ways to layout nodes. To get an idea of the kind of layout you can define, have a look at the *LayoutSpec Class References.

 

Example node

Here’s an example of a very simple custom ASDK node. All this node does is display a label (called an “ASTextNode” within the bounds of the node. The LayoutSpec for this node also defines an inset of 10 pixels all around the text node.

 

Other resources


The path to smooth scrolling UICollectionViews

03. March 2016 blog 0

We have a pretty standard app. It’s a list of items and if you click one of these items, you go to a detail page. This kind of list / detail paradigms are used very often. For instance in mail apps, note apps etc. It is not difficult to build such an app, but it is difficult to build such an app well. Once you start making a more complex UI you often run into performance issues. We found ourselves in such a situation last week.

UICollectionView

The list of houses we implemented in the funda app is backed by a UICollectionView. A UICollectionView is a a very flexible way of building a list because the size and layout of the items in the list can be customised. This allows us to build a simple vertical list at first but morph it into a grid once we convert our iPhone-only app to an iPad format. Unfortunately this flexibility comes at a price. Having dynamically sized cells and rich content within these cells is very expensive. Every time a cell is configured with the content of a house we make new labels, download a new image and place all these elements at their correct location. Most of these actions are done on the main thread by default and thus slow down or halt the actual scrolling of the list. Additionally, we used Auto Layout to layout all the elements in the cell and this was certainly not helping our performance either.

Enter ASyncDisplayKit

While searching for a solution for this performance issue I ran across AsyncDisplayKit. This library made by facebook makes it possible to construct and layout views (they call it “nodes”) in a background thread. By doing all the heavy lifting in the background, the main thread of the app remains responsive and the list scrolls very smoothly.

So that’s where we are right now. I made an initial attempt to integrate ASDK in our current architecture but it proved to be quite tricky. Since our collection cells have a dynamic height there