1

下面是我用来重试 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];
}
4

6 回答 6

3

我刚才遇到了同样的问题......在头疼之后我解决了......: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

于 2010-07-20T00:28:58.517 回答
2

您可以将操作延迟一点时间间隔,以让窗口有时间订购:

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

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

于 2010-04-26T18:30:06.543 回答
0

此代码仅适用于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];
//  }
}
于 2010-04-26T17:28:02.777 回答
0

另一种选择是更改 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];
于 2012-02-13T15:02:06.480 回答
0

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

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

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

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

也许这也行得通。

于 2010-08-13T22:58:40.777 回答
-1

您需要致电:

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

关闭警报视图。

于 2010-04-26T16:24:36.610 回答