Discover how to improve user experience in iOS development by incorporating two essential features: a UI that unveils when data is loading and a UI that allows users to refresh their data. Our tutorial guides you through the process of adding a loader and a refresh in an app development workflow.
Key Insights
- The tutorial focuses on enhancing the User Experience (UX) in iOS development, particularly when interacting with the web.
- Two primary UX features were discussed: adding a loader to indicate that data is loading and adding a refresh function for users to manually update data.
- Both features aim to prevent user frustration that may occur if the app's data doesn't load due to service failures and the user isn't alerted of the issue.
- For adding a loader, the tutorial provides step-by-step coding instructions, including initiating the loader, positioning it, and stopping it once data loading is complete.
- For adding a refresh, the tutorial walks through the process of enabling the Refreshing function in the Table View Controller section, creating a "refresh" method, and incorporating a line of code that clears the data in the model.
- Through following these steps, beginner iOS developers can avoid common UX pitfalls and create applications that meet user expectations for seamless interactions with external data.
Enhance your iOS development skills with this detailed tutorial covering the addition of a loader and refresh functionality, key aspects of user experience.
This exercise is excerpted from Noble Desktop’s past app development training materials and is compatible with iOS updates through 2021. To learn current skills in web development, check out our coding bootcamps in NYC and live online.
Topics Covered in This IOS Development Tutorial:
Adding a Loader, Adding Refresh
Exercise Preview
Exercise Overview
Now that we are interacting with the web, there’s a few things we should put into place to improve the User Experience (UX). We are all used to using apps on our phones and Apple has set the bar high in terms of User Experience. In fact Apple has defined the concept of good user experience and certain things are expected by users. The first is “friendly messaging” when something goes wrong. For instance, let’s say the app’s data didn’t load because the user’s cell or WiFi service failed, etc. What you don’t want to do is let a user sit there for a few minutes and not give them an indication that something went wrong. This will cause frustration and lead to users not wanting to use your app. Two of the things that are expected when dealing with external data are:
- UI that lets a user know data is loading
- UI that allows the user to refresh their data
Getting Started
-
If you completed the previous exercise you can skip the following sidebar. We recommend you finish the previous exercises (1B–4C) before starting this one.
If you completed the previous exercise, Jive Factory.xcworkspace should still be open. If you closed it, re-open it (from yourname-iOS Dev Level 2 Class > Jive Factory).
If You Did Not Complete the Previous Exercises (1B–4C)
- Close any files you may have open and switch to the Desktop.
- Navigate to Class Files > yourname-iOS Dev Level 2 Class.
- Duplicate the Jive Factory Ready for Improving the UX folder.
- Rename the folder to Jive Factory.
- Open Jive Factory > Jive Factory.xcworkspace.
Adding a Loader
- In the Project navigator, go to BandsTableViewController.swift.
-
In the viewDidLoad method, add the following bold code:
override func viewDidLoad() { super.viewDidLoad() let loader = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray) FirebaseApp.configure() bandsModel.fetch {[weak self] () -> () in if let strongSelf = self { strongSelf.tableView.reloadData() }
This creates an instance of a standard Apple UIApplication loader, also known as a spinner! You will likely recognize it when you see it.
-
Set the frame position for the loader and align it in the center by adding the following code:
override func viewDidLoad() { super.viewDidLoad() let loader = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray) loader.frame = CGRect(X: (self.view.frame.size.width-40)/2, y: (self.view.frame.size.height-40)/2, width: 40.0, height: 40.0) FirebaseApp.configure() bandsModel.fetch {[weak self] () -> () in if let strongSelf = self { strongSelf.tableView.reloadData() }
-
Next add the loader to our main view:
let loader = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray) loader.frame = CGRect(X: (self.view.frame.size.width-40)/2, y: (self.view.frame.size.height-40)/2, width: 40.0, height: 40.0) self.view.addSubview(loader) FirebaseApp.configure()
-
Get the loader spinning by adding the bold code:
let loader = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray) loader.frame = CGRect(X: (self.view.frame.size.width-40)/2, y: (self.view.frame.size.height-40)/2, width: 40.0, height: 40.0) self.view.addSubview(loader) loader.startAnimating() FirebaseApp.configure()
-
The loader should stop spinning once the data is complete. To do this, we need to call the stopAnimating() method on the loader from within our fetch() method. Add the following bold code:
FirebaseApp.configure() bandsModel.fetch {[weak self] () -> () in if let strongSelf = self { loader.stopAnimating() strongSelf.tableView.reloadData() } }
Go ahead and Run to see the spinner in action. Pay close attention to the Simulator, as the spinner will only flash for a second before the data loads.
Adding Refresh
- Return to Xcode.
- In the Project navigator, click on Main.storyboard.
- At the bottom left of the Editor, click the Show Document Outline button
if it’s not already showing.
- In the Document Outline, select Bands (within Bands Scene).
- In the Utilities area on the right, click the Attributes inspector tab
.
- In the Table View Controller section, next to Refreshing, set the menu to Enabled.
-
In the Project navigator, go to BandsTableViewController.swift and add the following bold code to the viewDidLoad method (and don’t worry about the error message):
self.view.addSubview(loader) loader.startAnimating() self.refreshControl?.addTarget(self, action: #selector(BandsTableViewController.refresh), for: UIControlEvents.valueChanged) FirebaseApp.configure()
-
Create a method called refresh and add it below the viewDidLoad method as shown below:
} @objc func refresh() { }
-
Add this line to the refresh method. It will clear the data in the model:
func refresh() { bandsModel.bandDetails.removeAll(keepingCapacity: false) }
-
We need to call the fetch method again. Select the code shown below and copy (Cmd–C) it:
bandsModel.fetch {[weak self] () -> () in if let strongSelf = self { loader.stopAnimating() strongSelf.tableView.reloadData() } }
-
As shown below, paste (Cmd–V) the code inside the refresh method:
func refresh() { bandsModel.bandDetails.removeAll(keepCapacity: false) bandsModel.fetch {[weak self] () -> () in if let strongSelf = self { loader.stopAnimating() strongSelf.tableView.reloadData() } } }
-
Update the pasted code by replacing the stopAnimating() line with the bold code:
func refresh() { bandsModel.bandDetails.removeAll(keepCapacity: false) bandsModel.fetch {[weak self] () -> () in if let strongSelf = self { strongSelf.refreshControl?.endRefreshing() strongSelf.tableView.reloadData() }
- Time to test. Make sure your WiFi/internet connection is turned on.
- Hit Run.
- Once the table has loaded, click and drag the cell down until you see the animated loader, which simulates a refresh!
If you have time, continue with the bonus exercises to customize the app for iPad.