gpambrozio / BlockAlertsAnd-ActionSheets

Beautifully done UIAlertView and UIActionSheet replacements inspired by TweetBot
http://codecropper.com/2012/01/replicating-tweetbots-alerts-and-action-sheets/
MIT License
1.41k stars 268 forks source link

Calling a 2nd Alert/Sheet in a Block causes Window issues #28

Closed coneybeare closed 11 years ago

coneybeare commented 12 years ago

There are several valid reasons why a seconds alert view would be called after a sheet button was tapped, or text entry was entered. In my app, I use it to throw validation errors, etc....

Before the code for the first alert/sheet is run to make it animate out, the second alert show code gets triggered from the block and gets added to the view. The problem is that after the first alert subsequently animates out, it returns key focus to what it assumes is the previous top window. But at this point, the window of the second alert is on top of the previous top window.

This means that the second alert/sheet will be on screen and forefront, but will be unresponsive as all the taps are sent to the previous top window.

There are a few ways to tackle this... One way is simply telling people not to do this. I think a better way though is to emulate the default UIAlertView and AlertSheet behavior. When 2 UIAlertViews are set to call, they are queued in some internal mechanism, and the second is shown after the first is dismissed. This would solve the problem and make it more robust in the future as it ensures that only 1 alert or sheet is on screen at any given time, and prevents the bug described above. Thoughts?

ddavtian commented 12 years ago

I faced the same issue and put in a few small and very simple changes (not sure if this clean enough, but seems to be ok thus far, at least in my testing. https://github.com/ddavtian/BlockAlertsAnd-ActionSheets.git

Now you can push multiple BlockAlerts into a queue and they are shown in sequence once one is dismissed. Let me know if this is the right direction to go with this.

coneybeare commented 12 years ago

I think this is the wrong approach. I implemented it in BlockBackground so the queue would also prevent BlockActionSheets from showing over BlockAlertViews. Unfortunately, my code has strayed quite far from your original so a pull request is probably out of the question, but I can send you a link over DM if you would like to take a look my approach.

ddavtian commented 12 years ago

Ahh, since I didn't use BlockActionSheets in my project, I overlooked them.

mysticvalley commented 12 years ago

I am also have same issue as explained above. I have a game app which is question answer app so there are lot of pop ups coming and going and if the user taps some pop up fast enough, the BlockAlertView goes to unresponsive state as @coneybeare explained in 1st post. Did you guys come up with any solutions? Any advice suggestions are highly appreciated.

Thank you!

coneybeare commented 12 years ago

I solved it in my app called The Last Shot, but the changes are too drastic to merge a pull request here. I used the same approach as I described 3 comments up.

bendytree commented 12 years ago

I'd love to see a fix for this using a queue.

For now I patched it by modifying the dismissWith... function to keep track of the last time an alert was dismissed. Then changed the show function to delay itself if necessary - to give the animating alert enough time to dismiss. Huge hack, but took 15 lines & lets me stack alerts.

b2github commented 12 years ago

I fixed by adding the following statements in BlockAlertView.m and BlockActionSheet.m. It seem to works better.

BlockAlertView.m

- (void)show
{
    if ([BlockBackground sharedInstance].keyWindow) {
        [self performSelector:@selector(show) withObject:nil afterDelay:0.3];
        return;
    }
    .
    .
    .
}

and in BlockActionSheet.m

- (void)showInView:(UIView *)view
{
    if ([BlockBackground sharedInstance].keyWindow) {
        [self performSelector:@selector(showInView:) withObject:view afterDelay:0.3];
        return;
    }
    .
    .
    .
}

but i don't use BlockTextPromptAlertView, so i don't have solution for this.

cheers,

bendodson commented 11 years ago

Just a note that the above didn't work for me. I instead altered it so that instead of:

if ([BlockBackground sharedInstance].keyWindow)

it used:

if (![BlockBackground sharedInstance].hidden)

Seems to be working at the moment.

albertschulz commented 11 years ago

I experienced the same problem, could you maybe upload the code fix to the repo ?

barrettj commented 11 years ago

This should be fixed by https://github.com/gpambrozio/BlockAlertsAnd-ActionSheets/commit/09d3b71f723791ed96fc070f91956f0bc3581705