Understanding threads

You've seen the term thread a couple of times now, but you never learned explored any of the details about threads. For instance, you never really learned what a thread is, or how a thread works. This section aims to make the subject of threading a lot clearer to you so you can fully understand what a thread is, and why they are such a vital part of building apps.

A good way to mentally think of a thread is a stack of instructions. In iOS, your app typically starts off with a single thread: The main thread. This thread is also known as the UI thread. It's called the UI thread because the main thread is where all of the user interface elements are drawn, rendered, and pushed to the screen. Anything that is related to the user interface must be executed on the main thread, so if you consider a thread as a stack of instructions, it becomes easy to see why it's important that the main thread doesn't become stuck performing a very slow instruction:

The preceding figure depicts a timeline where all code is executed on the main thread. Notice how we can't update the interface until the fetch data and parse json instructions are completed. Also note that fetching data takes a lot longer than displaying the interface or handling a tap. During the fetch data instruction, the app will not be able to update any user interface elements, or process any gestures or taps. This means that the app is practically frozen until the data is fetched and parsed.

Obviously, a good, responsive application can't afford to wait for slow instructions. The interface should always respond to user input; if this isn't the case, the app will feel slow, buggy, choppy, and just all-round bad. This is where multithreading becomes interesting.

We can run multiple instruction stacks at the same time. Each stack is called a thread, and we can execute certain instructions on a different thread to ensure that the interface remains responsive:

This second figure depicts a more desirable scenario. The main thread only handles user- interface-related tasks such as handling taps, animating loaders, and scrolling. The background thread takes care of the tasks that don't relate to the user interface and could potentially take a while to finish. By removing these instructions from the main thread and placing them on a different thread like iOS does by default for networking, we ensure that our app remains responsive, even if the network requests take several seconds to finish or never finish at all.

Your app can utilize a large number of threads for different tasks.

The number of threads isn't infinite, so even if you use threading like you should, you should still make sure that you optimize your code as much as possible to avoid locking up several threads with slow code.

In Chapter 22, Discovering Bottlenecks with Instruments, we used instruments to locate a piece of code that was slow. This resulted in an instruction on the main thread that took a very long time to complete, resulting in a frozen interface. Threading would not have solved this issue. The code that was slow was tightly related to the user interface because the collection view can't be rendered without calculating the layout first. This is a scenario where it's extremely important to make sure that you write optimized code, instead of simply relying on threads for anything that's slow.

Now that we've established an understanding of threads and how they can be utilized in your apps, let's have a look at how to manually offload tasks to different threads.