方法的名称tabBarController:didSelectViewController:
应该表明停止选择为时已晚。它的返回类型void
表明您对此无能为力。而是专注于其中包含“will”或“should”的方法名称,并返回诸如BOOL
s 之类的类型tabBarController:shouldSelectViewController:
。因此,这里有一些基本代码可以满足您的需求。
我不知道您的测试视图控制器的实际类名,所以我将QuizController
用作类名。QuizController
是一个UIViewController
子类。
测验控制器.m
@interface QuizController () <UITabBarControllerDelegate,UIActionSheetDelegate>{
BOOL _testInProgress;
}
@end
@implementation QuizController
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
// When a tabs view controller is presented viewDidAppear: will be called so here we will set this view controller as the tabBarController delegate so we get the callback.
self.tabBarController.delegate = self;
}
-(void)startQuiz{
_testInProgress = YES;
// Begin testing code
}
-(void)stopQuiz{
// Score test record results
_testInProgress = NO;
}
-(void)cancelQuiz{
// Throw out results
_testInProgress = NO;
}
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
if (!_testInProgress) return YES;
// If trying to select this controller then who cares?
if (viewController == self) return YES; // Or NO. Just don't show the sheet.
UIActionSheet *action = [[UIActionSheet alloc] initWithTitle:@"You are in the middle of a test. Are you sure you want to switch tabs?"
delegate:self
cancelButtonTitle:@"Continue Test"
destructiveButtonTitle:@"Abort Test"
otherButtonTitles:nil];
// Lets cheat and use the tag to store the index of the desired view controller.
action.tag = [self.tabBarController.viewControllers indexOfObject:viewController];
[action showFromTabBar:self.tabBarController.tabBar];
return NO;
}
-(void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex{
if (buttonIndex == actionSheet.destructiveButtonIndex){
[self cancelQuiz];
// The above cheat pays off.
[self.tabBarController setSelectedIndex:actionSheet.tag];
}
}
编辑(回应引用的评论)
我对你的例子有点困惑。目前,我的“参加考试”课程是 UIViewController。您是否建议我用上面的 QuizController 替换它?
不,我建议您采用此代码并将设计模式集成到UIViewController
处理您的测试的子类中。虽然这是一个工作示例(假设您提供 UI 来切换_testInProgress
ivar。)
我是否将当前的 UITabBarController 留在原处?
是的。
那是目前我的 appdelegate 和 rootController。
嗯?你UITabBarController
几乎肯定是你的rootViewController
。但是除非你做了一些非常奇怪AppDelegate : UITabBarController <UIApplicationDelegate>
的事情,顺便说一下不要这样做,那么你的“appdelegate”和你的不太可能UITabBarController
是一样的。你更有可能AppDelegate
是你tabBarController
的代表。
如果只是tabBarController.delegate
在外观上设置属性是不好的(很可能是),即一些其他对象需要成为tabBarController
的委托,那么您必须将消息转发到该视图控制器以查看是否有测试进步。为此,您实际上可以将示例中的几乎所有代码保持不变。当然,您必须删除self.tabBarController.delegate = self;
in viewDidAppear:
。并将以下内容放入您的AppDelegate
(假设是tabBarController
's 代表):
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
if ([tabBarController.selectedViewController respondsToSelector:@selector(tabBarController:shouldSelectViewController:)]){
return [(NSObject <UITabBarControllerDelegate>*)tabBarController.selectedViewController tabBarController:tabBarController shouldSelectViewController:viewController];
}
return YES;
}
这个实现基本上将回答问题的责任转发给视图控制器,前提是它会回答问题。
如果选择了“参加考试”选项卡,我会在那里检查并在我的“参加考试”类中调用初始化方法。
在我看来,当用户点击选项卡时,应该简单地选择“参加测试”视图控制器。它的视图应该包含一个按钮,上面有“开始测试”的效果。但那只是我的个人意见。
但无论如何,应用程序对用户是否参加考试的了解应该驻留在管理考试的视图控制器中。