ViewController堆栈

时间:2013-07-19 00:10:33

标签: iphone ios objective-c uiviewcontroller modalviewcontroller

所以我的应用程序逻辑存在问题,根据用户的凭据,我的应用程序的主视图是否应该在登录视图被取消后在主视图上显示一个tableview或只是显示主要登录视图被解除后查看。

所以目前,我向服务器发送一个http post请求,然后我收到一个令牌,然后再拨打一个电话,以获取用户拥有的列表项数量,比如游戏。

如果用户只有一个游戏,我希望显示主视图,但如果用户有多个游戏,那么用户应该看到一个桌面视图,按下其中一个单元格然后以模态方式关闭该表格以显示MAINVIEW。

通常我有这3个控制器,至少这是我在考虑实现方式的方式,不确定它是否正确。

假设控制器A是登录,控制器B是表视图,控制器C是主视图。

控制器C位于堆栈的底部,而控制器A位于堆栈的顶部。但可能的是,控制器B可能会或可能不会根据来自控制器A的信息显示。当我说堆栈底部时,我的意思是如果用户尚未登录,则会显示登录视图(控制器A)没有主视图上的动画(控制器C)。因此从技术上讲,主视图(控制器C)总是被加载,但只有在登录视图被正确提交的凭证解除后,数据才会被提供给它。

以下是在mainviewcontroller(控制器C)中实现的一些方法,用于检查用户是否已登录,如果他们没有,那么应用技术上首先通过mainviewcontroller然后呈现登录视图。我知道这是使用应用程序开发的登录模式的方法,但我不是100%:

- (void)showLoginViewAnimated:(BOOL)animated {
    NSLog(@"[MainViewController] Show login view controller");
    PowerOneLoginTabBar *loginVC = [[PowerOneLoginTabBar alloc] init];
    [self presentViewController:loginVC animated:NO completion:nil];
}

- (void)logoutHandler:(NSNotification *)notification {
    NSLog(@"[MainViewController] Logout handler");
    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"userLoggedIn"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    [self showLoginViewAnimated:YES];
}

在mainview的viewdidLoad中(viewcontroller C):

 BOOL isUserLoggedIn = [[NSUserDefaults standardUserDefaults] boolForKey:@"userLoggedIn"];
    if( !isUserLoggedIn || (!setAuthenticationKey || [setAuthenticationKey isKindOfClass:[NSNull class]]))
        [self showLoginViewAnimated:NO];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logoutHandler:) name:LOGOUT_NOTIFICATION object:self.view];

这是我在登录viewcontroller(控制器A)中实现的登录处理程序:

- (void)authenticateHandler:(NSNotification *)notification {
    NSLog(@"[LoginViewController] Authenticate handler");

    NSDictionary *userDict = [notification userInfo];



    BOOL isUserAuthenticated =
    //[username isEqualToString:[userDict objectForKey:@"username"]] &&
    //[password isEqualToString:[userDict objectForKey:@"password"]] &&
    [api_Key isEqualToString:[userDict objectForKey:@"apiKey"]] &&
    ([_auth isEqualToString:[userDict objectForKey:@"authKey"]]);

    [[NSUserDefaults standardUserDefaults] setBool:isUserAuthenticated forKey:@"userLoggedIn"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    if( isUserAuthenticated ){

        NSLog(@"Authentificated");
        [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];

    } else {
        NSLog(@"Not Authentificated");
        [self showAlert];
    }
}

在loginview的viewDidLoad方法中(viewcontroller A):

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(authenticateHandler:) name:AUTHENTICATE_NOTIFICATION object:self];

如果你们能给我一种架构或者万无一失的理论,我们可以做到这一点会很棒。

因为目前我正在使用所显示的主视图关闭登录视图,但后来我以模态方式(动画)呈现了tableview,这是不可取的。所以你可以想象一个视图通过动画被解雇然后一秒钟你看到主视图,然后通过动画在主视图上呈现tableview。我不希望用户在他们登录之后甚至看到主视图并在他选择游戏后查看详细信息,除非用户只有一个游戏!

请记住,在视图A和C之间显示tableview的唯一原因是因为用户可能有1个以上的游戏,但是如果他们只有1个游戏则从控制器A转到控制器C,而不是控制器A到控制器B到控制器C.

1 个答案:

答案 0 :(得分:1)

我不确定我是否完全理解这个问题,但这里有一些我希望有用的建议:

UINavigationController尤其适用于一堆vcs,特别是在我看来,在你出现的情况下。

主vc可以检查用户的登录状态,是否显示登录vc。它可以从假设用户有多个游戏可供选择并构建vc堆栈开始,如下所示:

- (void)viewDidAppear:(BOOL)animated {

    // notice I moved the logical or to make the BOOL more meaningful
    BOOL isUserLoggedIn = [[NSUserDefaults standardUserDefaults] boolForKey:@"userLoggedIn"] || (!setAuthenticationKey || [setAuthenticationKey isKindOfClass:[NSNull class]]);

    if (!isUserLoggedIn) {
        SelectGameVC *selectGameVC = // not sure how you build this, either alloc-init or get from storyboard
        // notice animation==NO, we're putting this on the stack but not presenting it
        [self.navigationController pushViewController:selectGameVC animated:NO];
        LoginVC *loginVC =  // alloc or use UIStoryboard instantiateViewControllerWithIdentifier
        // we push this one with animation, user will see it first
        [self.navigationController pushViewController:loginVC animated:YES];
    }
}

当loginVC完成登录时,它可以提出问题,用户是否有多个游戏?如果不止一个,只返回一个vc以显示我们堆叠在下面的SelectGame vc,否则一直弹回。

// LoginVC.m

// login successful
if (loggedInUser.games.count > 1) {
    // it's underneath us, remember?  we pushed it before we got here
    [self.navigationController popViewControllerAnimated:YES];
} else {
    // it's underneath us, but we don't need it, pop all the way back
    [self.navigationController popToRootViewControllerAnimated:YES];
}

顺便说一句,你的NSLog让我微笑,想起我曾经说过“认证”而不是“认证”的老朋友。