メソッドの名前は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に存在する必要があります。