阻止使用标签栏控制器(storyboard)访问UIViewControllers

我目前遇到我的iOS应用程序的问题。
我正在尝试包含一个渐进的login模式,即:使用可以访问一些应用程序,而不需要login。

所需function如下:

  • 在任何时候,用户都可以查看所有需要login的导航项目
  • 当用户尝试访问需要login的uview(控制器)时,系统会提示用户使用UIAlertView提示用户login。(最好在应用程序识别发起的segue目的地被限制时显示UIAlertView)。

起初,我使用了UIViewController的一个子类,在指定的初始化程序(initWithCoder)中,将检查NSUserDefaults以查看用户是否已login。然后我将其从子类中删除。 局限性如下:

  • 无法使用UIViewController的其他子类,即UITableViewController
  • UIAlertView出现后视图出现,我假设会导致错误,如果子类UIViewController假定用户login。

问题摘要:
我想知道如何有条件地阻止用户访问某些UIView(控制器)和UIViewController的子类,当发生这种情况时提供一个UIAlertView。

更新1
类别和/或协议是否可以成为可行的解决scheme?

更新2
CodaFi指出,单身人士是pipe理用户状态的一个很好的解决scheme。

现在我需要弄清楚如何控制用户的访问。
当我使用故事板时,我觉得最通用的实现是inheritanceUIStoryboardSegue,并在执行方法上检查用户是否尝试访问受限制的UIViewController(也许受限制的控制器具有指定所需状态的协议属性:login/出)。 然而这里的缺点是你不能在故事板graphics编辑器中selectUIStoryboardSegue的类/子类。 我知道,我可以做的编程方式,但是,这似乎乏味,因为我将不得不添加IBActions和类似的执行segues的方法,此外,我不认为这将适用于像navigationController和tabbarControllers元素的行为方式。

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

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

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

现在我明白我真正的问题是与tabbarcontrollerdelegate协议心理断开。

作为防止访问标签的解决scheme,我做了一个类来处理所述标签栏控制器

#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 

然后我把它连接到我的appDelegate在applicationDidFinishLaunching …

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

和瞧

好的,所以我有一个解决scheme的一部分。

它只适用于你可以select一个自定义的继续(我只写代码推,而不是模态)的情况下。

所有需要validation的控制器都使用协议“UIViewControllerAuthentication”,该协议包含一个方法来检索所需的validation状态。

 enum authenticationStatus { notLoggedIn = 0, noPassword = 1, loggedIn = 2 }; @protocol UIViewControllerAuthentication <NSObject> -(enum authenticationStatus)authStatusRequired; @end 

需要authentication的控制器符合此协议:

 -(enum authenticationStatus)authStatusRequired{ return loggedIn; } 

然后用这个进行authentication的push 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中使用自定义的继续

这是允许目的地控制器取消继续的好模式。
然而,它远离我想要的,因为我希望能够validation链接标签栏控制器和他们的孩子的segues。