我有一个教育应用程序正常使用标签栏。其中一个选项卡是对用户的测试。如果参加测试的用户选择另一个选项卡,我希望显示一个操作表,以确认他们确实要退出测试,因为他们的测试结果将会丢失。
我无法显示动作表。我在下面的前三个例子中遇到了语法错误。第四个例子将编译好,但应用程序中止。我无法弄清楚自我之后应该追求什么。或者,如果我的语法正确,可能其中一个例子也可以使用。
- (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];
最终,一旦我显示了要显示的操作表,我将继续选择选项卡或保留在测试视图中,具体取决于用户是否决定退出。任何帮助/建议将不胜感激。感谢。
答案 0 :(得分:1)
方法tabBarController:didSelectViewController:
的名称应该表明停止选择为时已晚。它的返回类型void
表示你无能为力。而是关注那些在其中包含“will”或“should”的方法名称,并返回BOOL
之类的类型,例如tabBarController:shouldSelectViewController:
。所以这里有一些基本代码可以满足您的需求。
我不知道测试视图控制器的实际类名,因此我将使用QuizController
作为类名。 QuizController
是UIViewController
子类。
<强> QuizController.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];
}
}
编辑(回应引用的评论)
我对你的例子有点困惑。目前,我的“考试” class是一个UIViewController。你是建议我用它替换它 你上面的QuizController?
没有。我建议您使用此代码并将设计模式集成到处理测试的UIViewController
子类中。虽然这是一个工作示例(提供您提供切换_testInProgress
ivar的UI。)
我是否要保留当前的UITabBarController?
烨。
这是我的appdelegate和rootController。
咦?您的UITabBarController
几乎肯定是您的rootViewController
。但除非你做了像AppDelegate : UITabBarController <UIApplicationDelegate>
之类的非常奇怪的事情,顺便说一下不这样做,那么你的“appdelegate”和你的UITabBarController
是不一样的。您AppDelegate
的{{1}}代表更有可能是tabBarController
。
如果仅仅在外观上设置tabBarController.delegate
属性很糟糕(并且它可能很好),即某些其他对象需要是tabBarController
的委托,那么你将不得不转发向该视图控制器发送消息以查看测试是否正在进行中。为此,您实际上可以保留示例中的几乎所有代码不变。当然,您必须删除self.tabBarController.delegate = self;
中的viewDidAppear:
。并将以下内容放入AppDelegate
(假设是tabBarController
的代理人):
-(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;
}
这个实现基本上是将问题的答案转发给视图控制器,只要它能回答问题。
我在那里检查是否选择了“参加考试”标签并拨打电话 我的“考试”课程中的初始化方法。
在我的意见中,当用户点击选项卡时,应该简单地选择“take test”视图控制器。它的视图应该包含一个按钮,其中包含“开始测试”的效果。但那只是我的意见。
但无论如何,应用程序对用户是否参加测试的了解应该驻留在管理测试的视图控制器中。
答案 1 :(得分:0)
[actionSheet showInView:[[[UIApplication sharedApplication] windows] objectAtIndex:0]];
你试过这个Link
吗?