Using Swift's enum associated values to represent a local or remote image

Leandro Linardos
Aug 25, 2017 · 4 min read

In mobile apps, when we ask a backend for an image, we usually don't receive the image ready to be rendered. We receive a URL instead. We access this URL, get the image data, instance the image and render it. The reasons are obvious, if we include the possible thousands of kilobytes of the image in a HTTP response, the response size will be much bigger than the dozens of characters of a URL. This problem is solved with indirection.

Good ol’ ‘indirection’. Nuthin’ beats that!

Now, if our app needs to upload an image to a backend, we usually send a multipart request with the image or we make a post request with the base 64 encoded image in the body. Sometimes we even upload the image to a third-party server (like amazon S3) which gives us a URL which we forward to our backend.


So far, so good. Let's take a look at the next case: developing a sign-up screen. It needs the user's name, email and a profile photo. The user writes his name and his email, picks a picture from the camera roll (or takes a new photo) as his profile photo. Then he taps on the sign-up button and we upload the photo to the backend. After a moment, the backend responds with a nice 2xx status code.

The following user model will be all the code we need:

Another screen in our app is the profile screen. The profile screen shows the user's name, email and his profile photo. Immediately after the user's sign-up, we can hold the User instance in memory and populate the profile screen with it. But, what happens the next time the user uses the app? There will be no previous sign-up, so there will be no User instance to populate the profile screen.

This user profile data (name, email and profile photo) is in the backend, so we can ask the backend for the user profile data every time we enter the profile screen. Yeah! We have our missing data in a new User instance. But wait! The backend gives us the photo URL which we can't render. So, our previous model will not work. What's missing? The photo URL. Ok, let's add it to our model:

And we can use it like this:

⚠ Warning 1: we have two Optionals for a mandatory property:photoImage: UIImage? and photoURL: URL? .

⚠ Warning 2: we have the same prefix for two properties: photoImage: UIImage? and photoURL: URL? .

Conceptually, both properties represent the same entity: the user profile photo. It doesn’t matter if we have the image data in the device or if we have the URL from which we can get the image data, both are just a kind of source for the image. So, we can define a new type that represents this image and its source, and Swift’s enum associated values are great for this:

Spreading the changes, the new User model will look like:

And we can use it like this:

Obviously (or maybe not so obviously), the business rules can support non mandatory profile photo. In that case, we have at least two options:

  • add a none case in the Image enum, or
  • make photo optional in User

and handle the chosen option in show(photo: Image, on imageView: UIImageView, placeholderImage: UIImage).


That's the main idea. Furthermore, we can make the use of Image on an UIImageView easier using the following extension:

So, for local images we can do:

And for remote images it looks like:

This is very useful, for instance, if we allow the user to edit his profile photo in the profile screen. First, we create a remote image with the remote URL taken from the backend response, and then, if the user changes his photo, we create a new local image with that local photo.


NOTE 1: In the code snippets, for the sake of simplicity, I've used SDWebImage for downloading and caching images. Obviously, we can avoid the pod and use native tools.

NOTE 2: This solution is the result of a code review made at Codika.


Codika is an innovative software development company that motivates its members to research and share their improvements. We want to encourage all companies to innovate and increase the society’s quality of life.

Codika Solutions

)

Leandro Linardos

Written by

Codika Solutions

The development of mobile apps is our field of expertise. We specialize in Android and iOS platforms and provide solutions for tablets and smartphones suited to the requirements of our clients, who range from big companies to small-sized businesses. Dive into the world of mobile

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade