1

我目前遇到了我的 iOS 应用程序的问题。
我正在尝试采用渐进式登录模式,即:用户无需登录即可访问某些应用程序。

所需功能如下:

  • 用户可以随时查看所有需要登录的导航项
  • 当用户尝试访问需要登录的 uiview(controller) 时,他们将收到 UIAlertView 提示,要求他们登录。(最好在应用程序识别出启动的 segue 目标受限时出现 UIAlertView)。

起初我使用 UIViewController 的一个子类,在指定的初始化程序 (initWithCoder) 中,它会检查 NSUserDefaults 以查看用户是否已登录。然后我将其子类化。限制如下:

  • 不能使用 UIViewController 的其他子类,即 UITableViewController
  • UIAlertView 在视图出现后出现,如果子类 UIViewController 假设用户已登录,我假设这会导致错误。

问题摘要:
我想知道如何有条件地阻止用户访问某些 UIView(Controller) 和 UIViewController 的子类,以及在发生这种情况时出现 UIAlertView。

更新 1
类别和/或协议能否成为可行的解决方案?

更新 2
CodaFi 指出单例是管理用户状态的绝佳解决方案。

有了这个实现,我现在需要弄清楚如何控制用户的访问。
当我使用故事板时,我觉得最通用的实现是继承 UIStoryboardSegue,并在执行方法上检查用户是否试图访问受限的 UIViewController(也许受限控制器具有指定所需状态的协议属性:登录/出去)。然而这里的陷阱是你不能在故事板图形编辑器中选择 UIStoryboardSegue 的类/子类。我知道我可以以编程方式执行此操作,但这似乎很乏味,因为我必须将 IBActions 添加到执行 segues 的方法中,而且我认为这不适用于 navigationController 和 tabbarControllers 等元素的行为方式。

有没有人有一个可行的解决方案来限制用户的导航?

更新 3
我已经为这个问题添加了一个答案,但是我仍然认为它没有答案,因为我写的答案没有考虑导航栏控制器之间的 segues。但是,它可能对某些人有所帮助。

4

2 回答 2

2

所以,我已经回答了如何使用自定义转场来做到这一点。

现在我明白了我真正的问题是与 tabbarcontrollerdelegate 协议的心理脱节。

作为防止访问选项卡的解决方案,我创建了一个类来处理所述选项卡栏控制器

#import <Foundation/Foundation.h>

@interface TabBarDelegate : NSObject<UITabBarControllerDelegate,UIAlertViewDelegate>{
    UITabBarController *cachedTabBarController;
}

@end

#import "TabBarDelegate.h"

@implementation TabBarDelegate

-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
    NSLog(@"%s",__FUNCTION__);
    NSLog(@"Pretending the user isnt logged in");

    if(true){
        NSString *message = [NSString stringWithFormat:@"You require an account to access %@",viewController.tabBarItem.title];
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Account Required" message:message delegate:self cancelButtonTitle:@"Okay" otherButtonTitles: @"Login",@"Create Account",nil];
        [alert show];
        //Hold tabbarcontroller property for alert callback
        cachedTabBarController = tabBarController;
        return false;
    }

    return true;
}

-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
    if(cachedTabBarController){
        switch (buttonIndex) {
            case 1:
                //Login
                [cachedTabBarController performSegueWithIdentifier:@"tabBarToLogin" sender:cachedTabBarController];
                break;
            case 2:
                //Sign up
                [cachedTabBarController performSegueWithIdentifier:@"tabBarToSignup" sender:cachedTabBarController];
                break;
            default:
                break;
        }
        //Release tab bar controller from memory
        cachedTabBarController = nil;
    }
}

@end

然后我在applicationDidFinishLaunching中将它连接到我的appDelegate ...

//Hook up tab bar delegate
    mainTabController = (UITabBarController*)self.window.rootViewController;
    mainTabBarDelegate = [[TabBarDelegate alloc] init];
    mainTabController.delegate = mainTabBarDelegate;

和瞧

于 2012-04-27T04:47:50.743 回答
0

好的,所以我有一部分解决方案。

它仅适用于您可以选择自定义 segue 的情况(我只编写了推送代码,而不是模态代码)。

协议“UIViewControllerAuthentication”适用于所有需要身份验证的控制器,该协议包含一个检索所需身份验证状态的方法。

enum authenticationStatus {
notLoggedIn = 0,
noPassword = 1,
loggedIn = 2
};

@protocol UIViewControllerAuthentication <NSObject>

-(enum authenticationStatus)authStatusRequired;

@end

需要身份验证的控制器符合此协议:

-(enum authenticationStatus)authStatusRequired{
return loggedIn;
}

然后将其用于经过身份验证的推送 segue

@interface SeguePushWithAuth : UIStoryboardSegue

@end
-(void)perform{
    NSLog(@"custom segue destination : %@",self.destinationViewController);
    NSLog(@"custom segue source : %@",self.sourceViewController);
    NSLog(@"custom segue dest conforms to protocol : %i",[self.destinationViewController conformsToProtocol:@protocol(UIViewControllerAuthentication)]);

    if([self.destinationViewController conformsToProtocol:@protocol(UIViewControllerAuthentication)]){
        UIViewController <UIViewControllerAuthentication> *destination = (UIViewController <UIViewControllerAuthentication> *)self.destinationViewController;
        if (!((int)[AccountModel userAuthStatus] >= (int)[destination authStatusRequired])) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Authentication" message:@"You need an account to access this area" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Login",@"Create Account", nil];
            //alert
            [alert show];
            return;
        }
    }

    [[self.sourceViewController navigationController] pushViewController:self.destinationViewController animated:true];
}

@end

然后在 uistoryboard 中使用自定义 segues

这是允许目标控制器取消转场的好模式。
然而,它远不是我想要的,因为我希望能够验证将标签栏控制器链接到他们的孩子的 segues。

于 2012-04-19T14:25:39.873 回答