Showing a loading indicator is the first thing you will do with MBProgressHUD, and it takes only a few lines of code. Your app starts a slow task, such as a network request, and you want the user to know the app is working. You show the HUD, run the task in the background, and hide the HUD when the task finishes. This guide shows you the exact code for Objective-C and Swift, and it explains the rules that keep the HUD working correctly.
Before you write any code, make sure MBProgressHUD is installed in your project. You can install it with Swift Package Manager, CocoaPods, Carthage, or by adding the source files directly. The install guides in this series cover each method. Once it is installed, import it in your view controller: import MBProgressHUD in Swift, or #import <MBProgressHUD/MBProgressHUD.h> in Objective-C. The library requires iOS 9.0 or later and ARC.
The Three Step Pattern
The pattern has three steps, and you will use it everywhere. First, show the HUD on the main thread, right before the slow work starts. Second, run the slow work on a background queue, so the interface stays responsive. Third, when the work finishes, hide the HUD back on the main thread. That is the whole pattern.
In Swift, the show step looks like this: let hud = MBProgressHUD.showAdded(to: self.view, animated: true). That line creates the HUD, adds it to your view, and shows it with an animation. The hide step looks like this: hud.hide(animated: true). In Objective-C, the show step is MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES], and the hide step is [hud hideAnimated:YES]. Both versions do the same thing.
Run the Slow Work in the Background
The slow work must run on a background queue, not on the main thread. If you run it on the main thread, the interface freezes, and the HUD itself will not animate, because the main thread is too busy to draw it. The user sees a frozen screen, which is exactly what the HUD is supposed to prevent.
In Swift, you can run the work on a background queue like this: DispatchQueue.global(qos: .userInitiated).async { // Do the slow work here, then come back to the main thread to hide the HUD }. Inside that block, do the slow work, such as fetching data from a server. When the work is done, switch back to the main thread with DispatchQueue.main.async, and hide the HUD there. In Objective-C, you use dispatch_async with a global queue, then dispatch_async back to the main queue to hide the HUD.
Add a Label So the User Knows What Is Happening
A spinner alone tells the user to wait, but a label tells them what they are waiting for. You can set the label text right after you show the HUD. In Swift, write hud.label.text = “Loading”. In Objective-C, write hud.label.text = @”Loading”. You can also set a details label with more information, such as hud.detailsLabel.text = “Fetching your data”. Keep the text short and honest. If the task is loading data, say so. If it is saving a file, say that instead.
You can also change the label while the task runs. For example, if your task has stages, you can update the label to show the current stage. Remember that label changes are interface work, so they must happen on the main thread. If you update the label from a background thread, the change may not appear, or the app may behave strangely.
Delay the HUD for Very Fast Tasks
Sometimes a task finishes so fast that the HUD flashes on the screen for a fraction of a second, which looks bad. MBProgressHUD has a setting called graceTime that fixes this. It delays the HUD by a short time, such as half a second. If the task finishes before the delay ends, the HUD never appears at all. If the task takes longer, the HUD appears as normal.
In Swift, set hud.graceTime = 0.5 before the task starts. In Objective-C, set hud.graceTime = 0.5. The value is in seconds. A grace time of half a second works well for most tasks. For a task that usually takes a few seconds, you can leave the grace time at zero and show the HUD right away.
Keep the HUD Visible Long Enough
The opposite problem is a HUD that disappears too fast for the user to notice. If a task finishes in a tenth of a second, the HUD flashes and vanishes, which feels glitchy. MBProgressHUD has a setting called minShowTime that fixes this. It keeps the HUD visible for a minimum time, such as one second, even if the task finishes sooner.
In Swift, set hud.minShowTime = 1.0. In Objective-C, set hud.minShowTime = 1.0. The value is in seconds. A minimum show time of one second works well for most tasks. Combine it with a grace time, and your HUD will appear only when the task is slow enough to matter, and stay visible long enough to feel smooth.
Show the HUD for a Network Request
The most common place to use this pattern is a network request. Your app asks a server for data, and the user waits for the answer. Show the HUD right before you start the request, and hide it in the completion handler when the data arrives. Set the label to something honest, such as “Loading”, so the user knows the app is fetching data and not frozen.
When the request finishes, check for an error before you hide the HUD. If the request failed, hide the HUD and show an error message, such as “Could not load data, please try again”. Do not just hide the HUD and leave the screen empty, because the user will not know what happened. A short error message is much better than silence, and it gives the user a clear next step.
The same pattern works for a login request, a file upload, or any other task that talks to a server. Show the HUD, start the request, and hide the HUD in the completion handler. The user sees the spinner while the request runs, and they see the result as soon as it arrives. That flow feels responsive, even when the network is slow.
Here is a short checklist for a clean loading indicator:
- Confirm you show the HUD on the main thread before the slow work starts
- Confirm you run the slow work on a background queue, not the main thread
- Confirm you hide the HUD back on the main thread when the work finishes
- Confirm you set a short label so the user knows what is happening
- Confirm you set a grace time so fast tasks do not flash the HUD
- Confirm you set a minimum show time so the HUD does not vanish too fast
Conclusion
Showing a loading indicator with MBProgressHUD is a simple three step pattern. Show the HUD on the main thread with showAdded, run the slow work on a background queue, and hide the HUD back on the main thread when the work finishes. Add a short label so the user knows what is happening, and use graceTime and minShowTime to keep the HUD smooth for fast and slow tasks alike. The same pattern works in Objective-C and Swift, and it works for network requests, file saves, logins, and any other task that makes the user wait. Once you learn it, you will use it in almost every screen of your app.
Read next: How to Install MBProgressHUD with CocoaPods, How to Show a Progress Bar with MBProgressHUD, How to Customize MBProgressHUD



Pingback: Show a Progress Bar with MBProgressHUD