【问题标题】:iOS programmatically triggered segue is performed multiple times on successiOS 以编程方式触发的 segue 在成功时执行多次
【发布时间】:2015-05-01 17:07:49
【问题描述】:

我将我的应用程序连接到一个 REST API 以登录用户。登录过程完成后,我使用 NSNotificationCenter 通知控制器登录成功,并让应用程序执行 segue 以将用户带到主菜单。这是我的代码:

//perform log in, or show error message
-(void)logInAttemptComplete:(NSNotification *)notification
{
Boolean loginSuccessful = (Boolean)[[notification userInfo] objectForKey:@"loginSuccessful"];

[SVProgressHUD dismiss];
//if the suer was successfully logged in, take him to the main menu
if(loginSuccessful)
{
    //go to the main menu
    [self performSegueWithIdentifier:@"logInSuccessfulSegue" sender:self];
}
else
{
    //copy error code and display appropriate error
    int errorCode = [[[notification userInfo] objectForKey:@"HTTP Message"] intValue];
    //404 no server, 401 wrong password/no user
    if(errorCode==401)
    {
        //create and show error alert view
        UIAlertView *loginErrorAlertView = [[UIAlertView alloc] initWithTitle:@"Log In Failure" message:@"Wrong credentials. Check your Username and/or Password." delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
        [loginErrorAlertView show];
    }
    else
    {
        //create and show error alert view
        UIAlertView *loginErrorAlertView = [[UIAlertView alloc] initWithTitle:@"Log In Failure" message:@"Failed to contact server, please try again later." delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
        [loginErrorAlertView show];
    }
}
}

问题是,如果第一次尝试登录不成功,假设需要 X 次尝试才能成功登录,那么 segue 会执行 X 次。当然,它确实出现在主菜单上,但最终结果很丑陋。任何想法如何解决这一问题?也许我应该避免使用 segue 并以编程方式将 hte 用户直接带到另一个控制器?

编辑回答

所以我通过添加行出错了

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logInAttemptComplete:) name:@"logInNotification" object:nil];

在按下登录按钮的功能内。

我通过在登录尝试失败后删除观察者来修复它

if(loginSuccessful)
{
//go to the main menu
[self performSegueWithIdentifier:@"logInSuccessfulSegue" sender:self];
}
else
{

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"logInNotification" object:nil];

【问题讨论】:

    标签: ios objective-c iphone segue nsnotificationcenter


    【解决方案1】:

    我会使用两种不同的通知,这段代码似乎比它应该的要复杂。

    您自己没有提供登录代码,所以我只能笼统地回答。创建两个通知(一个成功,一个登录失败)。登录控制器根据登录尝试的结果发送任一通知。

    您将上述方法拆分为两个方法,在发送任一通知时调用它们。

    您的代码可能如下所示:

    [manager GET:stringWithURLforRequest parameters:nil success:^(AFHTTPRequestOperation *task, id responseObject) {
    
       // ...
       [[NSNotificationCenter defaultCenter] postNotificationName:@"LogInSuccessful" object:nil userInfo:nil];
    
    } failure:^(AFHTTPRequestOperation *task, NSError *error) {
    
       // ...    
       [[NSNotificationCenter defaultCenter] postNotificationName:@"LogInFailure" object:nil userInfo:@{ @"HTTP Message":statusCodeNumber}];
    
    }];
    

    ... 你只需要添加另一个通知来监听你的另一个视图控制器。如果您这样做,您可以更安全地区分登录失败和成功(更好的语义)。

    【讨论】:

    • 我用我的用户模型的登录代码更新了我的代码……或者至少是登录操作
    • 如果我创建一个从未使用过的 NSNotification 监听器可以吗?
    • 为什么从来没有使用过?您只需实现两种方法,它们对成功或失败通知以及适当的事物做出反应。
    【解决方案2】:

    据我了解,您正在发送成功通知,如果重试,它会被调用太多次。

    单行修复方法是停止在成功方法中收听该通知。

    所以你会有一些类似的东西(伪代码)

    - (void)loginAttempt:(NSNotifcation*)notif{
        if (success){
    //Stop listening to that notification, so the method never gets called again
        performSegueWithIndetifier
        }else{
    
        //retry
    
        }
    }
    

    另一种肮脏的单线方法是保留尝试次数的 ivar,并且仅在该数字当前等于 0 时才调用 perform segue。

    我认为我的解决方案将解决您的问题,但是如果您有时间,我建议您以一种仅在需要调用时才调用 segue 或忽略其他 X 成功的回调的方式来审查您的设计.一个简单的想象方法是在上一次登录之前不重试结果。因此,在您真正知道自己是否失败(无论是超时还是成功或其他任何事情)之前,您都不会重试。

    【讨论】:

      【解决方案3】:

      如果您的userInfo 中的@"loginSuccessful" 是NSNumber,则使用:

      BOOL loginSuccessful = [notification.userInfor[@"loginSuccessful"] booleanValue];
      

      在原始代码中,如果对象不是nil(如果我理解正确的话,它总是如此),您总是会得到值 YES 的 loginSuccessful,因为您检查的是对象的存在而不是它的值。

      你在这一行使用了 NSNumber:

      @{@"loginSuccessful":@YES}
      

      @YES 只是 [NSNumber numberWithBool:YES] 的缩写

      根据this header Boolean 只是 unsigned char 所以你正在签署指向这个 char 的指针,它永远是真的(不是 NULL)。

      【讨论】:

      • 但我仍然进行了类型转换并且它工作正常,并不是每次都触发segue,只有当它是肯定的时候。无论如何,我做了你推荐的,因为它“更正确”但问题仍然存在
      • 从您在问题中提出的内容来看,我认为问题可能出在服务器端。
      【解决方案4】:

      找到了:

      问题是控制器一直在“侦听”,即使由于发送失败的消息

      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logInAttemptComplete:) name:@"logInNotification" object:nil];
      

      在按下登录按钮的功能中。

      我所要做的就是添加

      [[NSNotificationCenter defaultCenter] removeObserver:self name:@"logInNotification" object:nil];
      

      之后的一行
      if(loginSuccessful)
      {
      //go to the main menu
      [self performSegueWithIdentifier:@"logInSuccessfulSegue" sender:self];
      }
      else
      {
      

      其他检查。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多