Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Showing the hud then hiding it immediately leaves the hud with alpha 0 over the main view preventing user interaction #15

Open
ergodic1 opened this issue Jan 9, 2015 · 23 comments
Assignees
Labels

Comments

@ergodic1
Copy link

ergodic1 commented Jan 9, 2015

We've got a long running task that sometimes can be skipped. We figure that out in a background thread.
We popped up a KVNProgress up, then due to the fact the background task could be skipped, dismissed it almost immediately. This left a hud with alpha = 0 on the screen and we couldn't interact with it.

We've solved this by being smarter about the display, but perhaps there should be a NSOperationQueue that performs the animations making sure that the hud can never be in this state.

@ergodic1 ergodic1 changed the title Showing an indeterminate progress then hiding it immediately leaves a screen with alpha 0 overlaying the main view preventing user interaction Showing the hud then hiding it immediately leaves the hud with alpha 0 over the main view preventing user interaction Jan 9, 2015
@kevin-hirsch
Copy link
Collaborator

Hello @ergodic1,

Are you using the latest version of KVNProgress, the 2.1.6?

@ergodic1
Copy link
Author

ergodic1 commented Jan 9, 2015

Yes, sure am. I stepped through it in the debugger, and in:

  • (void)endDismissWithCompletion:(KVNCompletionBlock)completion
    {
    KVNProgress *progressView = [self sharedView];

    if (progressView.state == KVNProgressStateDismissing) {
    ...

progressView.state was KVNProgressStateShowed, even though previously it had been KVNProgressStateDismissing. It was then I realised that there were timing issues and reimplemented our way of showing it. But it does seem risky to have the possibility of leaving a hud over the entire view with alpha=0.

I thought that if each show/hide was implemented in a nsoperationqueue with concurrent operations set to 1, then it would be guaranteed to be in a consistent state. Otherwise you are left with two competion async calls which could leave it in any such state depending on many factors.

@kevin-hirsch
Copy link
Collaborator

You are right. I'm going to implement NSOperationQueue.
It should be done next week. I'll keep you in touch from here ;)

Thanks! 👍

@kevin-hirsch kevin-hirsch self-assigned this Jan 9, 2015
@ergodic1
Copy link
Author

ergodic1 commented Jan 9, 2015

Great! It's an amazingly well done library :)

@kevin-hirsch
Copy link
Collaborator

You made my day! :)

@ergodic1
Copy link
Author

ergodic1 commented Jan 9, 2015

Thinking about it, one other way to solve it might be to pass in a block to get notified of when the progress hud was shown, then we can safely dismiss it. That might be simpler to implement, but would still retain some risk of strange states if you didn't know about this.

@kevin-hirsch
Copy link
Collaborator

I think I'm going to go for the NSOperationQueue solution, it will be safer.

@ergodic1
Copy link
Author

ergodic1 commented Jan 9, 2015

Yeah I think that's a good idea. Means no one can ever brick their app :)

@KiranPanesar
Copy link

Any updates with this one, @kevin-hirsch? We're experiencing this when the network connection finishes before the show animation finishes. So it happens in a very small number of cases, but has a huge effect on the app.

How would you intend the NSOperationQueue solution to work?

@kevin-hirsch
Copy link
Collaborator

@KiranPanesar, I will start working on it tomorrow but it will probably take a few days for the implementation of NSOperationQueue to be complete and tested.
A solution should be available next weekend ;)

@KiranPanesar
Copy link

Great. We were going to work on this issues internally at MobileX Labs, because we occasionally run into it. Instead, we can figure out the live blur issue (#18), as we'll be needing that same solution for other parts of our app. 👍

@kevin-hirsch
Copy link
Collaborator

That would be much appreciated! :)

@KiranPanesar
Copy link

@kevin-hirsch We're actually working on this issue now (we're planning on shipping an update to our app EOW, so we really need this fixed). We confirmed the root cause is as stated above.

We were talking about implementing NSOperationQueue but think it might be overkill. So now the question is: Why are you checking the state of the HUD before removing from the superview? Pretty sure we could just remove that line and not experience this issue any more.

@kevin-hirsch
Copy link
Collaborator

Hi @KiranPanesar, the first check of [self sharedView].state == KVNProgressStateHidden could be removed.
But I cannot remove the [self sharedView].state == KVNProgressStateDismissing state because if you do:

   [KVNProgress show];
   [KVNProgress dismiss];
   [KVNProgress showWithStatus:@"loading again"]; // should cancel the previous dismiss in some way
  1. The dismiss call with be delayed so that the first show call shows the HUD a minimum of time for the user before being dismissed.
  2. But then, before the dismiss is actually done, we call a second show which we do not want to be dismissed yet.
  3. It should then cancel it some way the dismiss action that is waiting so the second show will be able to display itself as long as we wish.

I hope I am clear on that special case.
Would that be enough for you if I remove the first [self sharedView].state == KVNProgressStateHidden check for now?

@mobilejohnw
Copy link

Hi @kevin-hirsch, this is John Welch, working with Kiran at MobileX Labs. Your suggested fix won't address the frozen ui issue. With a single view app that does nothing else I can replicate the invisible dialog bug with the following lines in viewdidload:

   [KVNProgress showWithStatus:@"Test 1" onView:self.view];
   [KVNProgress showWithStatus:@"Test 2" onView:self.view];
   [KVNProgress dismiss];

This causes the progress dialog not to be removed from its superview, because of that internal state check. I'm trying to figure out what the minimum change that would address these race conditions would be. Restructuring with a queue (either dispatch_queue or NSOperationQueue) would address the ordering issue, but we are hoping for a simpler fix.

@kevin-hirsch
Copy link
Collaborator

I will check if it's possible to fix this issue without dispatch_queue's or NSOperationQueue's tonight. I'll keep you posted.

@ergodic1
Copy link
Author

Hey @mobilejohnw , one possible short term solution which I thought of might be to pass in a completion block:

[KVNProgress showWithStatus:@"Test 1" onView:self.view onceAnimationsFinished:^{
// do next task... just make sure not to call dismiss outside of this block and you should be fine...
}];

The KVNProgress library would just make sure the onceAnimationsFinished block was called as part of the show animation onCompletion. Just an idea that might help - this looked to be a simple fix when I considered it, but I wanted a guaranteed solution that would work under all circumstances.

@mobilejohnw
Copy link

Hi @kevin-hirsch, so, in our case, we'd kick off the update once the minimum animation time had passed and dismiss when that update completed. That would solve the race condition as long as we used that pattern consistently. Is this a change you'd be willing to publish? I'd like to avoid forking the library just for this bug. @KiranPanesar, care to chime in?

@kevin-hirsch
Copy link
Collaborator

@ergodic1, that is a good idea indeed but more for a temporary fix, because I don't really want user to have to call the show methods with a completion block to avoid this particular issue. This should preferably be handled internally in the KVNProgress.

@mobilejohnw:

  1. I thought about a solution to fix this issue and an NSOperationQueue could be great to be able to handle orders of operations so you will be sure that dismiss is called after all the previous show's had been showed during their minimum display time.
  2. You are talking about what you would do in your case in your previous post. Did you actually write some code already? Or you have a good idea of how to implement this fix?

@ergodic1, @KiranPanesar, @mobilejohnw, Thank you for helping me on this one! 👍 :)

@mobilejohnw
Copy link

@kevin-hirsch, I have been investigating this problem, but don't have any code to share yet. I didn't want to implement an NSOperationQueue or dispatch_queue solution if I could make a simpler change, but will if I have to. I'll be working on this again later today, because as @KiranPanesar mentioned we do need a fix this week.

@FilipZawada
Copy link

Hey, has this been resolved? I'm seeing similar behavior in my app, likely due to this bug.

@KiranPanesar
Copy link

We are using @mobilejohnw's fork in our project: https://github.com/mobilejohnw/KVNProgress

It has resolved the issues we've experienced.

@FilipZawada
Copy link

Cool, let me give it a try

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants