26

How can I disable all Input while the UIActivityIndicatorView is spinning?

Thanks

Gueorgui Obregon
  • 5,077
  • 3
  • 33
  • 57
mica
  • 3,898
  • 4
  • 34
  • 62
  • 1
    If you add the spinner to a UIAlertView and then show the alert, then this will achieve what you are after. – Luke Mar 04 '12 at 11:44
  • You can also achieve a nice effect with [MBProgressHUD](https://github.com/matej/MBProgressHUD) but that may be heavier the you want depending on what you are trying to achieve. – FluffulousChimp Mar 04 '12 at 11:56
  • thanks Luke, how do I "destroy" the UIAlertView if I want it to disapear. Is it OK to have 0 buttons? – mica Mar 04 '12 at 11:58
  • It's perfectly fine to not have buttons. Just call [someAlertView dismissWithClickedButtonIndex:0 animated:YES]; – Brandon Schlenker Mar 04 '12 at 12:18
  • Please go through this Link [Has Detailed Conversation about this Topic][1] [1]: http://stackoverflow.com/questions/5404856/how-to-disable-touch-input-to-all-views-except-the-top-most-view – Kamar Shad Mar 04 '12 at 13:31

4 Answers4

56

You can call beginIgnoringInteractionEvents when you start the spinner

[[UIApplication sharedApplication] beginIgnoringInteractionEvents];

and endIgnoringInteractionEvents when you stop it.

[[UIApplication sharedApplication] endIgnoringInteractionEvents];

Just make sure your code always comes to the point where you call endIgnoringInteractionEvents, otherwise your app will freeze (from the users point of view).

Rok Jarc
  • 18,765
  • 9
  • 69
  • 124
  • Thanks, works fine. But as I can see, that the view does "remember" a touch and fire the event after the endIgnoreInteractionsEvent. Can this behavior be changed? – mica Mar 04 '12 at 14:10
  • 1
    @mica: wow, that's an interesting observation - haven't noticed this before. I'll take a look. If you're in a hurry you can hijaack application's main window's `sendEvent:` and there decide (ie. by checking some kind of flag if spinner is animating or not) if you'll send an event down the responder chain or ignore it. One way to hijaack this window is [here](http://stackoverflow.com/questions/9251174/detect-if-the-user-has-touched-the-screen/9293321#9293321) (the answer with `MyKindOfWindow` definition). – Rok Jarc Mar 04 '12 at 14:26
  • @mica: looks like you've find a bug. According to [documentation](https://developer.apple.com/library/ios/#DOCUMENTATION/EventHandling/Conceptual/EventHandlingiPhoneOS/MultitouchEvents/MultitouchEvents.html) this shouldn't happen: "Turning off delivery of touch events for a period. An application can call the UIApplication method beginIgnoringInteractionEvents and later call the endIgnoringInteractionEvents method. The first method stops the application from receiving touch events entirely; the second method is called to resume the receipt of such events. – Rok Jarc Mar 04 '12 at 14:38
  • 1
    Thanks for your investigation. In this special case the behavior is OK for me. If not, I think I would go the way to place a transparent view over all others, while the UIActivityIndicator is spinning. – mica Mar 04 '12 at 15:42
  • 2
    Thank's that one Helped!! – Jayprakash Dubey Nov 06 '13 at 06:54
  • It does. Syntax would be something like `UIApplication.sharedApplication().beginIgnoringInteractionEvents()`... – Rok Jarc Feb 16 '16 at 11:02
9

In Swift 3.0:

To disable interaction:

UIApplication.shared.beginIgnoringInteractionEvents() 

To restore interaction:

UIApplication.shared.endIgnoringInteractionEvents() 
Alexei - check Codidact
  • 22,016
  • 16
  • 145
  • 164
Gr8Warrior
  • 699
  • 7
  • 11
1

Just an addition to rokjarc answer. Here an example of watchdog to keep app alive. You can call always with some critical interval, maybe 10 sec. And if you need to enable within 10 sec, just call "enable" method.

UIWindow * __weak mainWindow;

- (void)disableGlobalUserInteractionForTimeInterval:(NSTimeInterval)interval
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        mainWindow = [[[UIApplication sharedApplication] windows] lastObject];
    });

    [mainWindow setUserInteractionEnabled:false];

    if (interval > 0)
    {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(interval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self enableGlobalUserInteraction];
        });
    }
}

- (void)enableGlobalUserInteraction
{
    if (mainWindow)
    {
        [mainWindow setUserInteractionEnabled:true];
    }
}
Mike Glukhov
  • 1,758
  • 19
  • 18
0

In Swift 5:

// activity indicator starts
view.isUserInteractionEnabled = false

...

// activity indicator stops
view.isUserInteractionDisabled = true
borninla
  • 51
  • 11