UIAlertView 关闭并没有真正关闭

发布于 2024-08-30 11:33:52 字数 589 浏览 10 评论 0原文

下面是我用来在 FBConnect 会话上重试的代码。当 [self loginToFaceBook] 触发时,FBConnect 会向“窗口”添加一个子视图,该子视图仍然是 UIAlert 视图,因此当 UIAlert 真正关闭时,它会带走 FBConnect 视图。关于等待 UIAlert 视图消失的最佳方法的任何想法。

-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    if([self respondsToSelector:@selector(alertContinue)]) {
        [self alertContinue];
    }
}
-(void)alertContinue
{
    SocialLiteAppDelegate *appDelegate = (SocialLiteAppDelegate *)[[UIApplication sharedApplication] delegate];
    [appDelegate.fbSession logout];
    [self loginToFaceBook];
}

Below is the code I'm using to do a retry on an FBConnect session. When the [self loginToFaceBook] fires FBConnect adds a subview to 'window' which is still the UIAlert view, so when the UIAlert really dismisses it takes the FBConnect view with it. Any idea as to the best way to wait for the UIAlert view to be gone.

-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    if([self respondsToSelector:@selector(alertContinue)]) {
        [self alertContinue];
    }
}
-(void)alertContinue
{
    SocialLiteAppDelegate *appDelegate = (SocialLiteAppDelegate *)[[UIApplication sharedApplication] delegate];
    [appDelegate.fbSession logout];
    [self loginToFaceBook];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

素年丶 2024-09-06 11:33:52

我刚才也遇到了同样的问题...
经过一番头痛之后,我解决了它...:D

(如果您不需要解释,只需查看示例代码和上面的几行...:D)

问题是,alertView 创建了另一个窗口,使其成为关键窗口,并将alertView的视图放入其中...现在,当您告诉FBConnect重新登录时,使用对话框和所有内容,它会在关键窗口内显示它自己。此时是alertView 的窗口。

所以我们只需要让警报窗口放弃它的关键状态。
我没有找到手动执行此操作的方法,但幸运的是它可以为您做到这一点。什么时候?在运行循环的末尾(实际上需要一点时间;))。

解决方案很简单,让警报的运行循环结束。您可以通过在后台运行重新登录方法来完成此操作。

[self performSelectorInBackground:@selector(loginToFaceBook) withObject:nil];

但是我们还有另外两个问题需要处理:

  • 正如我之前提到的,需要一些时间才能真正清理alertView的混乱(特别是窗口)。所以我们需要等待。
  • FBConnect 创建的对话框内部有一个 webView,而 WebView 不喜欢在后台......所以我们需要在主线程中调用它。

KennyTM 善意地建议不可能检查其他堆积的警报,我不同意...我使用了这段代码:

BOOL shouldWait = YES ; 

// wait for the alert view to dissmiss it's self 
while (shouldWait) {

    [NSThread sleepForTimeInterval:0.1];

    UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
    shouldWait = [keyWindow isKindOfClass:NSClassFromString(@"_UIAlertOverlayWindow")];
}

现在我不确定这在公共 API 中是否合法...但我认为有各种各样的警报检查关键窗口是否是警报视图窗口的其他方法...想到的另一种方法是尝试查看它的任何子视图是否属于“UIAlertView”类...就像这样:

for (UIView *subView in [keyWindow subviews]) {
    if (shouldWait = [subView isKindOfClass:[UIAlertView class]) {
        break;
    }
}

无论如何,我'我确信这是一个可以解决的问题......在我提交我的应用程序之后,如果我记得(我有记忆问题:/),我会让你们知道苹果是否批准了这些技术中的任何一个......

并且您需要的另一件事是在主线程上“显示”对话框。但这很简单:

FBStreamDialog* dialog = [[[FBStreamDialog alloc] init] autorelease];
[dialog performSelectorOnMainThread:@selector(show) withObject:nil];

如果您想使用会话初始化对话框,您还需要在主线程上执行此操作...

我有一个名为“showDialodWhenAppropriate”的方法,我在后台执行该方法。它进行等待,在适当的时候,我调用另一个名为“showTheDialog”的方法,我在主线程上调用该方法。

Facebook 或许应该自己实现这一点……但在他们实现之前,祝大家玩得开心。 :D

I had the same problem just now...
After a big headache i solved it... :D

(if you don't need the explanation, just look at the sample code, and the few lines above it... :D )

the thing is, the alertView creates another window, makes it the key window, and places the alertView's view in it... now when you tell FBConnect to log back in, with the dialog and all, it show's it's self inside the key window. which at the time is the alertView's window.

So we just need to make the alert's window to resign it's key status.
i did not find a way to manually do that, but luckily it does that for you. when? in the end of the run loop (and it actually takes a little bit of time ;) ).

the solution is pretty simple, let the alert's runloop end. you do this by running your re-login method in the background.

[self performSelectorInBackground:@selector(loginToFaceBook) withObject:nil];

but then we have two other issues to take care of:

  • as i mentioned before, it takes it a little while, to actually cleanup the alertView's mess (the window in particular). so we need to wait for it.
  • the dialog FBConnect creates has a webView inside, and the WebViews don't like being in the background... so we'll need call it in the main thread.

KennyTM has kindly suggested that it's impossible to check for other stacked alerts, i disagree... I've used this code:

BOOL shouldWait = YES ; 

// wait for the alert view to dissmiss it's self 
while (shouldWait) {

    [NSThread sleepForTimeInterval:0.1];

    UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
    shouldWait = [keyWindow isKindOfClass:NSClassFromString(@"_UIAlertOverlayWindow")];
}

Now i'm not sure if this is legal in the public API... but i think there are all kinds of other ways to check if the key window is the alert view's window... another one that comes to mind is to try and see it any of it's subView's is of the "UIAlertView" class... like so:

for (UIView *subView in [keyWindow subviews]) {
    if (shouldWait = [subView isKindOfClass:[UIAlertView class]) {
        break;
    }
}

anyways, i'm sure it's a solvable problem... and after i'll submit my app, and if i'll remember (i have memory problems :/ ) i'll let you guys know if apple approved any of these technics...

and the other thing you'll need to is to "show" the dialog on the main thread. but that's easy:

FBStreamDialog* dialog = [[[FBStreamDialog alloc] init] autorelease];
[dialog performSelectorOnMainThread:@selector(show) withObject:nil];

if you want to init the dialog with a session, you'll need to do that on the main thread as well...

I had a method called "showDialodWhenAppropriate" which i perform in the background. it does the waiting, and when it's appropriate, i call another method called "showTheDialog" which i call on the main thread.

Facebook should probably implement this themselves.. but until they do, have fun. :D

夜访吸血鬼 2024-09-06 11:33:52

您可以延迟一点时间间隔,让窗口有时间排序:

-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
    if([self respondsToSelector:@selector(alertContinue)]) {
        [self performSelector:@selector(alertContinue) withObject:nil afterDelay:0.05];
    }
}

当然,您需要确保没有其他堆积的警报(这是不可能用公共API检查的,因为这些警报可能来自系统(例如电池电量低、推送通知等)。

You may delay the action with a little time interval to let the window to have time to order out:

-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
    if([self respondsToSelector:@selector(alertContinue)]) {
        [self performSelector:@selector(alertContinue) withObject:nil afterDelay:0.05];
    }
}

Of course, you need to ensure there are no other stacked alerts (which is impossible to check with public API, because those alerts may come from the system e.g. low battery, push notifications, etc.).

情深缘浅 2024-09-06 11:33:52

此代码仅适用于animated = NO

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if(buttonIndex == alertView.cancelButtonIndex) { 
        exit(0); 
    }
    [alertView dismissWithClickedButtonIndex:buttonIndex animated:NO];
    if([self respondsToSelector:@selector(alertContinue)]) {
        [self alertContinue];
    }
}

-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
//  if([self respondsToSelector:@selector(alertContinue)]) {
//      [self alertContinue];
//  }
}

This code works only for animated = NO.

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if(buttonIndex == alertView.cancelButtonIndex) { 
        exit(0); 
    }
    [alertView dismissWithClickedButtonIndex:buttonIndex animated:NO];
    if([self respondsToSelector:@selector(alertContinue)]) {
        [self alertContinue];
    }
}

-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
//  if([self respondsToSelector:@selector(alertContinue)]) {
//      [self alertContinue];
//  }
}
半衾梦 2024-09-06 11:33:52

另一种选择是更改 FBDialog.m 代码。将这段代码更改

UIWindow* window = nil;//[UIApplication sharedApplication].keyWindow; // this does not work if you come from a UIAlertView!!!
if (!window) {
    window = [[UIApplication sharedApplication].windows objectAtIndex:0];
}

为:

UIWindow* window = [[UIApplication sharedApplication].windows objectAtIndex:0];

Another option is to change the FBDialog.m code. Change this bit of code:

UIWindow* window = nil;//[UIApplication sharedApplication].keyWindow; // this does not work if you come from a UIAlertView!!!
if (!window) {
    window = [[UIApplication sharedApplication].windows objectAtIndex:0];
}

to

UIWindow* window = [[UIApplication sharedApplication].windows objectAtIndex:0];
小巷里的女流氓 2024-09-06 11:33:52

同样的问题,但很容易解决。我使用计时器来触发我正在调用的 fb 方法。我试图向用户墙上发布消息。我还从 didDismissWithButtonIndex: 触发了该方法。

在FBDialog show:方法中,它调用当前窗口并显示新的对话框。我相信 FBConnect 使用的任何对话框都可以做到这一点。

我将计时器设置为半秒来触发该方法。它允许警报很好地关闭,然后 FBDialog 框在正确的窗口中打开。使用开关盒作为按钮索引,我可以实现以下效果。

    case 1:
            NSLog(@"Write On Wall");
            [self performSelector:@selector(postToWall) withObject:nil afterDelay:0.5f];
            break;

也许这也会起作用。

Same problem but easy fix. I used a timer to trigger the fb method I was calling. I was trying to post a message to the users wall. I was triggering the method from the didDismissWithButtonIndex: also.

In the FBDialog show: method, it calls the current window and displays the new dialog box. I believe any dialog FBConnect uses does this.

I triggered the method with a timer set to half a second. It allows the Alert to close nicely and then the FBDialog box opens in the correct window. Using a switch case for the button index, I have the following working great.

    case 1:
            NSLog(@"Write On Wall");
            [self performSelector:@selector(postToWall) withObject:nil afterDelay:0.5f];
            break;

Maybe that will work also.

三生殊途 2024-09-06 11:33:52

您需要调用:

 - (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated

来关闭警报视图。

You need to call:

 - (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated

to dismiss the alert view.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文