メソッドの名前はtabBarController:didSelectViewController:、選択を停止するには遅すぎることを示している必要があります。そのリターンタイプvoidは、それについてできることはあまりないことを示しています。代わりに、「will」または「should」が含まれているメソッド名に注目し、 。BOOLなどのsのような型を返しますtabBarController:shouldSelectViewController:。だからここにあなたが望むことをするいくつかの基本的なコードがあります。
テストのViewControllerの実際のクラス名がわからないため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];
}
}
編集(引用されたコメントに応じて)
私はあなたの例について少し混乱しています。現在、私の「テストを受ける」クラスはUIViewControllerです。上記のQuizControllerに置き換えることを提案していますか?
UIViewControllerいいえ。このコードを使用して、テストを処理するサブクラスにデザインパターンを統合することをお勧めします。_testInProgressこれは実際の例ですが( ivarを切り替えるためのUIを提供します)。
現在のUITabBarControllerをそのまま残しますか?
うん。
それは現在私のappdelegateとrootControllerです。
は?あなたUITabBarControllerはほぼ間違いなくあなたrootViewControllerです。しかし、あなたがのような非常に奇妙なことをしていなければAppDelegate : UITabBarController <UIApplicationDelegate>、ちなみにそれをしないでください、そしてあなたの「加害者」とあなたUITabBarControllerが同じである可能性は非常に低いです。おそらくあなたAppDelegateはあなたtabBarControllerの代理人です。
プロパティを外観に設定するだけtabBarController.delegateで悪い場合(そしてそれは非常にうまくいく可能性があります)、つまり他のオブジェクトをtabBarController'デリゲートにする必要がある場合は、メッセージをそのView Controllerに転送して、テストが行われているかどうかを確認する必要があります進捗。このため、実際には、例のほとんどすべてのコードを変更せずに残すことができます。もちろん、self.tabBarController.delegate = self;inを削除する必要があります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;
}
この実装は、基本的に、質問に回答する責任をViewControllerに転送します。
そこで「テストを受ける」タブが選択されているかどうかをチェックインし、「テストを受ける」クラスの初期化メソッドを呼び出します。
私の意見では、「テストを受ける」ビューコントローラは、ユーザーがタブをタップしたときに選択されるだけです。また、そのビューには、「テストの開始」を有効にするためのボタンが含まれている必要があります。しかし、それは私の意見です。
ただし、どのような場合でも、ユーザーがテストを受けているかどうかに関するアプリケーションの知識は、テストを管理するViewControllerに存在する必要があります。