UIActivityIndicatorView
UIActivityIndicatorView
is a UIKit control that displays a spinning indicator to show that a task is in progress, such as loading data or performing a network request. It is a subclass of UIView
and is commonly used to provide visual feedback during asynchronous operations. This document covers the key properties, methods, and usage of UIActivityIndicatorView
, along with examples and best practices.
Overview of UIActivityIndicatorView
A UIActivityIndicatorView
is a simple, lightweight control that animates a spinning wheel or similar indicator. It is ideal for indicating ongoing activity without specifying progress (unlike UIProgressView
). The control supports different styles and can be customized for color and behavior.
Creating a UIActivityIndicatorView
You can create a UIActivityIndicatorView
programmatically or via Interface Builder (storyboards/xibs).
Programmatic Example:
import UIKit
let activityIndicator = UIActivityIndicatorView(style: .medium)
activityIndicator.color = .systemBlue
activityIndicator.startAnimating()
view.addSubview(activityIndicator)
Key Properties of UIActivityIndicatorView
Below are the most commonly used properties of UIActivityIndicatorView
:
Property | Type | Description |
---|---|---|
style | UIActivityIndicatorView.Style | The visual style of the indicator (e.g., .medium , .large ). |
color | UIColor? | The color of the spinning indicator. |
isAnimating | Bool | Indicates whether the indicator is currently animating (read-only). |
hidesWhenStopped | Bool | If true , the indicator is hidden when not animating. |
activityIndicatorViewStyle | UIActivityIndicatorView.Style | Deprecated in iOS 13; use style instead. |
Available Styles (iOS 13+)
.medium
: A standard-sized indicator, suitable for most use cases..large
: A larger indicator for more prominent display.
Pre-iOS 13 Styles (Deprecated):
.gray
: A gray-colored indicator..white
: A white indicator..whiteLarge
: A larger white indicator.
Example: Configuring Properties:
activityIndicator.style = .large
activityIndicator.color = .systemGreen
activityIndicator.hidesWhenStopped = true
Key Methods of UIActivityIndicatorView
UIActivityIndicatorView
inherits methods from UIView
, but also provides methods specific to animation control:
Method | Description |
---|---|
startAnimating() | Starts the spinning animation. |
stopAnimating() | Stops the spinning animation (hides the view if hidesWhenStopped is true ). |
isAnimating | Returns true if the indicator is animating. |
Example: Controlling Animation:
activityIndicator.startAnimating() // Start spinning
activityIndicator.stopAnimating() // Stop spinning
Customizing Appearance
Color
Set the color
property to change the indicator’s tint.
Example:
activityIndicator.color = .systemRed
Hiding When Stopped
Set hidesWhenStopped
to true
to automatically hide the indicator when it stops animating.
Example:
activityIndicator.hidesWhenStopped = true
activityIndicator.stopAnimating() // Indicator is hidden
Size and Style
Choose .medium
or .large
based on the context. The indicator’s size is fixed for each style, but you can adjust its position using Auto Layout or frames.
Using UIActivityIndicatorView
Typical Use Case
Show the indicator during a task (e.g., network request) and hide it when the task completes.
Example:
func fetchData() {
activityIndicator.startAnimating()
// Simulate async task
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.activityIndicator.stopAnimating()
}
}
Combining with Other UI Elements
Pair the indicator with a label or overlay to provide context.
Example:
let label = UILabel()
label.text = "Loading..."
view.addSubview(label)
view.addSubview(activityIndicator)
label.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalTo(view.safeAreaLayoutGuide).offset(20)
}
activityIndicator.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalTo(label.snp.bottom).offset(10)
}
Best Practices
Use Sparingly: Display the indicator only during active tasks to avoid visual clutter.
Support Accessibility: Set
accessibilityLabel
andaccessibilityTraits
for VoiceOver.swiftactivityIndicator.accessibilityLabel = "Loading indicator" activityIndicator.accessibilityTraits = .updatesFrequently
Use Auto Layout: Set
translatesAutoresizingMaskIntoConstraints = false
and use constraints (e.g., with SnapKit).Provide Context: Pair with a label or other UI element to clarify what is loading.
Test on Devices: Verify appearance and animation on various screen sizes and iOS versions.
Troubleshooting
- Indicator Not Showing: Ensure
startAnimating()
is called and the view is added to the view hierarchy. - Indicator Not Hiding: Check if
hidesWhenStopped
istrue
andstopAnimating()
is called. - Appearance Issues: Verify
style
andcolor
compatibility with the iOS version. - Accessibility Issues: Test with VoiceOver to ensure proper feedback.
Example: Complete UIActivityIndicatorView Setup
import UIKit
import SnapKit
class ViewController: UIViewController {
let activityIndicator = UIActivityIndicatorView(style: .large)
let statusLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
// Configure activity indicator
activityIndicator.color = .systemBlue
activityIndicator.hidesWhenStopped = true
activityIndicator.accessibilityLabel = "Loading indicator"
// Configure label
statusLabel.text = "Tap to Load"
statusLabel.textAlignment = .center
view.addSubview(activityIndicator)
view.addSubview(statusLabel)
// Auto Layout with SnapKit
statusLabel.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.centerY.equalToSuperview().offset(-20)
}
activityIndicator.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalTo(statusLabel.snp.bottom).offset(10)
}
// Add tap gesture to simulate loading
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(startLoading))
view.addGestureRecognizer(tapGesture)
}
@objc func startLoading() {
statusLabel.text = "Loading..."
activityIndicator.startAnimating()
// Simulate async task
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.activityIndicator.stopAnimating()
self.statusLabel.text = "Loaded!"
}
}
}