Daniel García Baena
Daniel García Baena

Reputation: 1201

Don't allow user interaction when activity indicator view is visible

I have a view which contains two views. One of those views contains two buttons and some text labels. The other one, with alpha set to 0.25, has an UIActivityIndicatorView to tell the user that the app is working and he must wait until it finishes. If the user touch a button while the UIActivityIndicatorView is spinning, when the UIActivityIndicatorView stops, the app remember the user action and responds to it. How can I discard the user interaction that occur while the UIActivityIndicatorView is spinning?

Thanks for reading.

P.D.: Like is commented in this thread, I prefer do not to use any modal solution.

EDITED:

I am currently using this code and it does not work right.

- (void)viewDidAppear:(BOOL)animated {

  // The view appears with an UIActivityIndicatorView spinning.
  [self showResults]; // The method that takes a long time to finish.
  [self.activityIndicator stopAnimating];
  // When the showResults method ends, the view shows the buttons to the user.
  [self.activityIndicatorView setHidden:YES];
  [self.menuButton setEnabled:YES];
  [self.menuButton setUserInteractionEnabled:YES];
  [self.playButton setEnabled:YES];
  [self.playButton setUserInteractionEnabled:YES];
  [self.view setUserInteractionEnabled:YES];
  [self.interactionView setUserInteractionEnabled:YES];
}

Upvotes: 23

Views: 34199

Answers (11)

clopex
clopex

Reputation: 459

For swift 5 you can use:

self.view.isUserInteractionEnabled = false

and to enable all again:

self.view.isUserInteractionEnabled = true

If you have some lag problem, like freeze for about a couple of seconds just put this in:

DispatchQueue.main.async{}

Upvotes: 2

Gr8Warrior
Gr8Warrior

Reputation: 719

In Swift 3.0 To Disable interaction :-

UIApplication.shared.beginIgnoringInteractionEvents()

To restore interaction :-

UIApplication.shared.endIgnoringInteractionEvents()

Upvotes: 8

Mohsen Hosseinpour
Mohsen Hosseinpour

Reputation: 534

@IBAction func yourButtonPressed(sender: UIButton) {
if self.activityIndicator.isAnimating() {
//remember the action user asked of you using the sender
} else {
//do your stuff
return
}
yourButtonPressed(yourButton)
}

or you code use self.activityIndicator.animationDidStop to determine when to run your stuff

Upvotes: 1

vipin bansal
vipin bansal

Reputation: 896

Though answer is replied in earlier response, just like to add for information purpose "[self.activityIndicatorView setHidden:YES];" no need to call this method explicitly, because startAnimating/stopAnimating already take care of this. I'm assuming you are using default value of "hidesWhenStopped" property.

Upvotes: 0

ppalancica
ppalancica

Reputation: 4277

I found these methods very useful:

[[UIApplication sharedApplication] beginIgnoringInteractionEvents];

[[UIApplication sharedApplication] endIgnoringInteractionEvents];

Upvotes: 113

Dinesh Reddy Chennuru
Dinesh Reddy Chennuru

Reputation: 491

Use SVProgressHUD WrapperClass It have so many options to show ActivityIndicator
For Source Code Click Here !

[SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeBlack];


use above statement to disable background touches

[SVProgressHUD dismiss]

To enable background touches.

Upvotes: 1

Raja Jimsen
Raja Jimsen

Reputation: 230

To disable touch event in a view,

[[UIApplication sharedApplication] beginIgnoringInteractionEvents];

To enable touch event in a view

[[UIApplication sharedApplication] endIgnoringInteractionEvents];

Upvotes: 4

Omar Freewan
Omar Freewan

Reputation: 2678

just add

[self.view setUserInteractionEnabled:NO];  

before the

[self.activityIndicator startAnimating];  

and reenable it after

[self.activityIndicator stopAnimating];
[self.view setUserInteractionEnabled:YES]; 

Upvotes: 4

DavidM
DavidM

Reputation: 548

[_button setUserInteractionEnabled:NO];

That should disable it, just set YES for when you want to user to tap it.

BOOL i_am_ready_to_submit = NO;

-(void)action_finished{

[self.activityIndicator stopAnimating];

i_am_ready_to_submit = YES;

}

-(IBAction)submit_button{

if(i_am_ready_to_submit){

[self submit];

}

}

Upvotes: 4

octy
octy

Reputation: 6545

You could disable/enable the UIButtons based on the UIActivityIndicatorView being shown or not. Or, if you just want to "discard the user interaction" while the spinner is shown, in the button handler method:

- (void)buttonTapped:(id)sender {
    if ([spinner superview] != nil && [spinner isAnimating]) {
        return;
    }
    // ... the rest of your code
}

This example assumes that when you hide the UIActivityIndicatorView you call one of:

[spinner removeFromSuperview];

or

[spinner stopAnimating];

Upvotes: 1

djromero
djromero

Reputation: 19641

A quick solution: add a transparent or pseudo transparent view that cover the whole screen. Add your activity indicator on top of this view. When the wait period finishes, remove both views. Get some inspiration.

A better solution, because you can't hide the whole screen in all situations, is to manage the state of the app (ignore actions when the app is 'busy') and disable/enable the appropriate buttons and other controls depending on each app state.

Upvotes: 0

Related Questions