1

タブバーで正常に動作する教育アプリがあります。タブの1つは、ユーザーのテストです。テストを受けるユーザーが別のタブを選択した場合、テスト結果が失われるため、実際にテストを終了することを確認するためのアクションシートを表示したいと思います。

アクションシートを表示できません。以下の最初の3つの例で構文エラーが発生します。4番目の例は正常にコンパイルされますが、アプリは中止されます。私は自分の後に何をすべきか理解できません。または、構文が正しければ、他の例の1つが機能する可能性があります。

    - (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」が含まれているメソッド名に注目し、 。BOOLなどのsのような型を返しますtabBarController:shouldSelectViewController:。だからここにあなたが望むことをするいくつかの基本的なコードがあります。

テストのViewControllerの実際のクラス名がわからないためQuizController、クラス名として使用します。サブクラスですQuizControllerUIViewController

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に存在する必要があります。

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

このワンリンクを試しましたか

于 2012-09-09T05:34:52.910 に答える