Skip to content

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:

swift
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:

PropertyTypeDescription
styleUIActivityIndicatorView.StyleThe visual style of the indicator (e.g., .medium, .large).
colorUIColor?The color of the spinning indicator.
isAnimatingBoolIndicates whether the indicator is currently animating (read-only).
hidesWhenStoppedBoolIf true, the indicator is hidden when not animating.
activityIndicatorViewStyleUIActivityIndicatorView.StyleDeprecated 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:

swift
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:

MethodDescription
startAnimating()Starts the spinning animation.
stopAnimating()Stops the spinning animation (hides the view if hidesWhenStopped is true).
isAnimatingReturns true if the indicator is animating.

Example: Controlling Animation:

swift
activityIndicator.startAnimating() // Start spinning
activityIndicator.stopAnimating() // Stop spinning

Customizing Appearance

Color

Set the color property to change the indicator’s tint.

Example:

swift
activityIndicator.color = .systemRed

Hiding When Stopped

Set hidesWhenStopped to true to automatically hide the indicator when it stops animating.

Example:

swift
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:

swift
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:

swift
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 and accessibilityTraits for VoiceOver.

    swift
    activityIndicator.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 is true and stopAnimating() is called.
  • Appearance Issues: Verify style and color compatibility with the iOS version.
  • Accessibility Issues: Test with VoiceOver to ensure proper feedback.

Example: Complete UIActivityIndicatorView Setup

swift
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!"
        }
    }
}

Resources

Released under the MIT License.