I have a login screen on my iOS app. When I click login button I want to make sure that user should be displayed a loading image in center of the screen.

I found lots of different methods online but I am after a simplest method. I found a way to display activity Indicator with minimum code:

First of all, import your UI Kit:

import UIKit;

Then you have to initiate activity indicator:

let activityIndicator:UIActivityIndicatorView = UIActivityIndicatorView();

Then just copy paste this functions below which are self explainatory and call them whereever you need them:

func startLoading(){
    activityIndicator.center = self.view.center;
    activityIndicator.hidesWhenStopped = true;
    activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray;



func stopLoading(){ 



Although, I am still not convinced that it's the best way to do it. Could it still be reduced?

Here is how my screen looks with the code:

enter image description here

  • \$\begingroup\$ are you intending to use this activity indicator on multiple screens, or just on one viewController? \$\endgroup\$
    – dirtydanee
    Commented Dec 19, 2016 at 21:48
  • \$\begingroup\$ multiple screen because I want to use it on register, login even inside my protected controller section \$\endgroup\$
    – Lonare
    Commented Dec 19, 2016 at 23:39

3 Answers 3


There are a few things I would recommend to do.

  1. Usually, instead of disabling the interaction events there is an extra layer on top of all views that contains the activity indicator. So, instead of adding the activity indicator directly into the viewController's view, add it in another view first with clear background color and with 0.4 alpha.

  2. Right now the startLoading() function also sets up the activity indicator, what i would rather separate into a different function, like setupLoading()

  3. If you want to reuse the solution on other viewControllers, create a class or a protocol at least ecapsulating the logic. Also, it is better to present it on the UIApplication's keyWindow property, than just simply adding it to viewContollers view's.

  4. Prepare for the stopLoading() and startLoading() functions to be called from a background thread.

Finally, there are plenty of very good solutions already on the interwebs, that you could integrate into your project, like SwiftSpinner.

If you need further help, code examples, let me know and I will edit my answer.


1 It's better to have separate singleton class which will take care of all the activity indicator related tasks.
So it'll be easy to reuse it from anywhere the app.

2 Make variables and methods private if not required outside.

3 Also make sure that whenever this class perform anything related to UI, it must be on main thread.

4 Add activity indicator on root view controller, so no restrictions that it should be called from any view.

class LoaderController: NSObject {

static let sharedInstance = LoaderController()
private let activityIndicator = UIActivityIndicatorView()

//MARK: - Private Methods -
private func setupLoader() {

    activityIndicator.hidesWhenStopped = true
    activityIndicator.activityIndicatorViewStyle = .gray

//MARK: - Public Methods -
func showLoader() {

    let appDel = UIApplication.shared.delegate as! AppDelegate
    let holdingView = appDel.window!.rootViewController!.view!

    DispatchQueue.main.async {
        self.activityIndicator.center = holdingView.center

func removeLoader(){
    DispatchQueue.main.async {

Here's example use:

//call from any thread, any class

Tested in Swift 5, you can use the following simple extension:

// Activity Indicator Extension
var vSpinner : [UIView] = []

extension UIViewController {
    func showSpinner(onView : UIView) {
        let spinnerView = UIView.init(frame: onView.bounds)
//        spinnerView.backgroundColor = UIColor.init(red: 0.8, green: 0.8, blue: 0.8, alpha: 0.9)
        let ai = UIActivityIndicatorView.init(style: .medium)
        ai.center = spinnerView.center
        DispatchQueue.main.async {
    func removeSpinner() {
        DispatchQueue.main.async {

Within your async task use these two handy boys:

showSpinner(onView: self.view) Remember to replace self.view with any kind of view you desire

self.removeSpinner() Remove the loading indicator:

  • \$\begingroup\$ To the one who placed -1, please let me know why and what's the correct answer? \$\endgroup\$ Commented Dec 25, 2021 at 22:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.