Designing for slow cellular connections
Designing for iOS and designing web based products are more similar than you may think. Yes, the iOS codebase looks foreign, the tools you’re using are different, and the software release cycles are longer but there are some similarities.
For a web based product you’re probably familiar with designing empty states, handling exceptions(404/500) and communicating the state of your app to a user. You’ll have to do the same for iOS, but you’ll also want to design for slow cellular connections. Most of us are wired up in an office using ridiculous fast Wi-Fi, thunderbolts screens and are sitting in perfect lighting. However, you should be empathetic to the people who are using your product in different environments with various network connectivity.
iOS Network Connectivity
As a designer, understanding the iOS ecosystem is an advantage. You’ll have a holistic view of the system, you’re able to recognize device nuances and you’ll have a better understanding of the Native APIs. With that knowledge you can uncover constraints and better communicate with your engineers.
Part of that ecosystem includes network connectivity. For network connectivity it’s important to understand how iOS handles network degradation. Wi-Fi connections vary in speed but are still given priority over cellular networks. If you’re on a cellular network and your connection is performing poorly, it degrades from 4G to 3G to Edge. In some cases your network connection can be very volatile.
Network connectivity is important because the majority of the apps we build need to request data from outside sources. For an app to update with new data it needs to create a network connection. iPhones constantly traverse various networks conditions including overloaded and captive networks. The network condition will affect the experience of your app.
Creating a better user experience
User Perception & Motion Design
One way of providing a better experience for a slow cellular connection is through motion design. User’s have a binary perception when it comes to the speed of their mobile connection. Either they perceive an app to be fast, or slow. Any response above 1 second interrupts the user’s flow of thought, and makes them feel less in control to directly manipulate the app.
Motion design and subtle interactions can offset the perception of a slow app, making it appear faster and more stable. Motion design also aides in a user orientation, helps guide user focus, and can provide delight.
A common motion design pattern can be found when transitioning and loading a new collection view. If a user swipes from right-to-left on a collection view, the motion indicates that new content will load in their current viewport. Executing the animation directly after a gesture makes the app feel directly manipulatable, even though the content may take a few seconds to load. The animation gives the user explicit feedback that content is loading which creates the perception of a faster app.
Another way of providing a better experience is through interaction feedback. People build mental models around certain objects and tasks, including submitting forms and tapping into detailed views. For example — when submitting a form, a user expects the action being performed is also being executed. When a user taps the submit button in a form you should disable the submit button until you receive the response. This will prevent a user from either getting frustrated and/or sending 20 requests by furiously tapping submit.
People also build mental models around network connections. User’s expect feedback when there’s network latency or a disruptive connection. There are a few ways to give a user feedback during a network request:
Apple provides a UIActivityIndicatorView(spinner) and also the NetworkActivityIndicator(spinner located in the status bar which reflects the speed of your network connection). There are also various open source libraries that are available such as MBProgressHUD to show the both connective state and progress(ex: loading, still loading, complete).
Speed as a feature
Speed plays an important role when in a poor network connection. A fast app is a design feature that needs careful planning and implementation. Design teams should work closely with engineering to optimize performance. There’s a direct correlation between perception of speed, and latency of an app. Apps that take long to load contribute to user frustration and often results in the user abandoning and/or deleting the app completely.
Below are a few examples of apps that optimized performance and/or interactions to provide a better core experience:
The Technical Details
There are various ways to check a user’s network connection. AFNetworking and Apple’s Reachability API will give you information on the current connected state of a user. When you’re building the app I’d suggest throttling the network speed in Xcode’s iOS Simulator. Even better, turn on Airplane mode to see how your app reacts with no cellular connection. Does it throw random errors?
Handling the state of your user’s device
Know your user’s current connected state is the first step in deciding what experience to provide in the app. Use it as signal and not the source of truth. Remember that people are constantly traveling in-and-out of different levels of connectivity.
There are a few technical best practices to improve the user experience while on a poor network connection:
- Handle failures gracefully
- Gracefully degrade when network performance is slow (ex: If network connection is poor while streaming HD video, degrade to a lesser quality)
- Use a custom timeout value
- At an operating system level, the iOS timeout value is set to 5 minutes. 5 minutes is an incredibly long time for a user to wait for a response. I would suggest setting the timeout at a logarithmic scale(retry 1s, 15s, 45s, 2m, etc.)
- Separate network failures vs server failures
- Separating both failures will make it easier to debug in your logs
- Network failures shift the blame to the user, which in some cases, can be helpful (ex: If a user is in airplane mode and tries to access new data that requires a network request)
- Server failures are reserved when the fault is on the app or network. Whereas packet loss occurred and the user should be informed that his/her upload did not finish
- Serve resources based on user behavior
- There’s a balance between providing the smallest resource(what’s needed) vs. limiting the number or network requests
ex 1: An email client should download the first ~5 unread messages in one request. Assuming(preferably through data insights), that the user will tap through those specific views. This technique provides a better experience vs downloading each individual message on demand.
ex 2: A site that is serving a large data response may want to make one network request, at a good connection, instead of making multiple requests with the possibility of network packet loss.
- Leverage caching
- NSURLCache provides support for caching. Be conscious of what you cache and the cache expiration. You don’t want to take up too much space on your user’s phone.
- Allow users to cancel transactions that are taking too long
- Provide either a back button, cancel or gesture to keep the user in control of their experience.
Handling edge cases
Even if you follow the above best practices, you’ll still find some edge cases. An example of a critical edge case involves handling push notification permissions for a first time user. When a user is going in-and-out of networks, the client may not be in sync with the server. If the server never receives the Push Notification token, you should prompt the user with a second UIAlertController(iOS Modal) to ask for permission again. Initializing persistent modals is considered an anti-pattern but is necessary for the utility of some apps.
It’s pretty cool to see companies like Facebook create initiatives around slow connection speeds. Speed is an important part of any experience whether it’s digital or not. By designing for slow cellular connections you are providing the best experience for everyone, regardless of locale or network.