1

我有一个与标签栏配合良好的教育应用程序。其中一个选项卡是对用户的测试。如果参加测试的用户选择另一个选项卡,我希望显示一个操作表以确认他们确实想要退出测试,因为他们的测试结果将会丢失。

我无法显示操作表。下面的前三个示例出现语法错误。第 4 个示例将编译成功,但应用程序中止。我不知道应该去追求自我。或者,如果我的语法正确,其他示例之一可能会起作用。

    - (void)tabBarController:(UITabBarController *)tabBarController 
didSelectViewController:(UIViewController *)viewController {
NSLog(@"Tab Bar Controller reached");

UIActionSheet *actionSheet = [[UIActionSheet alloc]
                              initWithTitle:@"This will end the test.  
                              Are you sure you want to leave?"
                              delegate:self
                              cancelButtonTitle:@"Cancel"
                              destructiveButtonTitle:@"Yes, 
                              cancel the test."
                              otherButtonTitles:nil];
[actionSheet showInView:self.view];   
[actionSheet showInView:elements1AppDelegate.window];
[actionSheet showFromTabBar:self.tabBarController.tabBar];
[actionSheet showFromTabBar:self];

最终,一旦我显示操作表,我将继续选择选项卡或停留在测试视图中,具体取决于用户是否决定退出。任何帮助/建议将不胜感激。谢谢。

4

2 回答 2

1

方法的名称tabBarController:didSelectViewController:应该表明停止选择为时已晚。它的返回类型void表明您对此无能为力。而是专注于其中包含“will”或“should”的方法名称,并返回诸如BOOLs 之类的类型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 来切换_testInProgressivar。)

我是否将当前的 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;
}

这个实现基本上将回答问题的责任转发给视图控制器,前提是它会回答问题。

如果选择了“参加考试”选项卡,我会在那里检查并在我的“参加考试”类中调用初始化方法。

在我看来,当用户点击选项卡时,应该简单地选择“参加测试”视图控制器。它的视图应该包含一个按钮,上面有“开始测试”的效果。但那只是我的个人意见。

但无论如何,应用程序对用户是否参加考试的了解应该驻留在管理考试的视图控制器中。

于 2012-09-09T06:04:00.450 回答
0
[actionSheet showInView:[[[UIApplication sharedApplication] windows] objectAtIndex:0]];

你试过这个 One Link

于 2012-09-09T05:34:52.910 回答