2

シンプルなviewControllerがあります。ビュー コントローラはアニメーションを使用します。リストを表示している場合は、マップにアニメーション化されます。その際、マップをポイントするボタンもリストをポイントするように変更します。

したがって、同じボタン (実際には 2 つの異なるボタンですが、ユーザーには同じボタンとして表示されます) を押し続けることで、ユーザーはマップからリストに、またはその逆に切り替え続けることができます。

正常に動作します。いくつかのキャッチで。

ユーザーのタップが速すぎる場合はどうなりますか? 私のアプリケーションが実際に使用されることを考えると、それらを缶詰にしたり罰したりすることはオプションではないとだけ言っておきましょう。

これは現在のプログラムです:

-(void) transitiontoViewController:(UIViewController *)toViewController duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL))completion1
{


    [self enableButtonWithBool:false];
    UIViewController * fromController = self.last2ViewsInTheContainer.lastObject;
    if (fromController.view.superview!= self.ContainerView)
    {
        return;
    }
    [self transitionFromViewController:fromController toViewController:toViewController duration:duration options:options animations:animations completion:^(BOOL finished) {
        if (completion1 == Nil) //can't execute nil block. can be more elegantly done with [completion1 invoke] if there is such function. Anyway, do nothing if completion1 is nil
        {

        }
        else
        {
            completion1 (finished);
        }
        [self.last2ViewsInTheContainer addObject:toViewController];

        if (self.last2ViewsInTheContainer.count>2)
        {
            [self.last2ViewsInTheContainer removeObjectAtIndex:0];
        }
    }];

    [self enableButtonWithBool:true];
    [self ReloadorRedraw];
}

シンプルなトランジション。機能の最後で指摘したいのは、2 つのコントローラー ビューが同じサブビューを持っていることです。関数の最後で遷移がまだ完了していないようです。古いView Controllerは実際には削除されていません。

ReloadorRedraw の内容は次のとおりです。

-(void)ReloadorRedraw;
{
    BGCRBadgerStandardViewViewController * listOrMap = nil;
    if ([self.last2ViewsInTheContainer lastObject]==self.filterController)
    {
        [self.changeFilterButton setBackgroundImage:[UIImage imageNamed:filterBarOpenImageString] forState:UIControlStateNormal];
        listOrMap = self.last2ViewsInTheContainer[0];
    }
    else
    {
        [self.changeFilterButton setBackgroundImage:[UIImage imageNamed:filterBarCloseImageString] forState:UIControlStateNormal];
        listOrMap = self.last2ViewsInTheContainer.lastObject;
    }

    if (listOrMap==self.listBusinessViewController)
    {
        self.navigationItem.rightBarButtonItem=self.mapButton;
    }
    else
    {
        self.navigationItem.rightBarButtonItem=self.listButton;
    }
}

クリックが速すぎると、次のメッセージが表示されました。の外観トランジションの開始/終了の不均衡な呼び出し。

その後、アプリは無効な状態になります。

この状況を改善する 1 つの方法は、アニメーションが終了するまでボタンを「無効」にすることです。

-(void) transitiontoViewController:(UIViewController *)toViewController duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL))completion1
{


    [self enableButtonWithBool:false];
    UIViewController * fromController = self.last2ViewsInTheContainer.lastObject;
    if (fromController.view.superview!= self.ContainerView)
    {
        return;
    }
    [self transitionFromViewController:fromController toViewController:toViewController duration:duration options:options animations:animations completion:^(BOOL finished) {
        if (completion1 == Nil) //can't execute nil block. can be more elegantly done with [completion1 invoke] if there is such function. Anyway, do nothing if completion1 is nil
        {

        }
        else
        {
            completion1 (finished);
        }
        [self.last2ViewsInTheContainer addObject:toViewController];

        if (self.last2ViewsInTheContainer.count>2)
        {
            [self.last2ViewsInTheContainer removeObjectAtIndex:0];
        }

    [self enableButtonWithBool:true];
    [self ReloadorRedraw];
    }];

}

基本的に動いてます

    [self enableButtonWithBool:true];
    [self ReloadorRedraw];

完成ブロックへ。

関数 enableButtonWithBool は、次の単純な関数です。

-(void)enableButtonWithBool: (BOOL) enable
{
    self.mapButton.enabled=enable;
    self.listButton.enabled= enable;
    self.changeFilterButton.enabled =enable;
    self.searchBar.enabled =enable;
}

これはうまくいきます。

私のパートナーはそれが好きではありません。これは、無効化されたボタンがわずか .3 秒であっても見苦しく見えるためです。それが自分の利益のためであっても、ユーザーはそれを好まないでしょう。

したがって、基本的には、アプリケーションが終了するまで待つのではなく、ボタンをすばやく再度有効にする必要があります。

しかし、それを行いながら、ユーザーの素早いクリックに耐えられる堅牢なアプリケーションを作成するにはどうすればよいでしょうか?

「実際の」移行がいつ完了したかを誰かが説明してくれると助かると思います。古いもののスーパービューから実際に削除し、新しいもののサブビューに追加することを意味します。アニメーションは、トランジションやビュー構造を実際に変更しない単なる「映画」ですか?

4

4 に答える 4

6

userInteractionEnabledアニメーションの間、ボタンを NO に設定します。これにより、ボタンが無効になりますが、外観が変わったり、アクション メソッドが複雑になったりすることはありません。

于 2012-10-21T14:43:46.083 に答える
2

ボタンをクリックすると、ボタンに触れ続けないように視覚的なインジケーターであるスピナーに変更されます。スピナーは、タッチされたボタンを置き換える新しいボタンであるため、そのボタンにそれ以上ヒットすることはありません。スピナーをボタンに戻すコード。

- (void) saveButtonPressed:(id) sender {
//remove keyboard if up
 [[self view] endEditing:YES];

//start a spinner to let user know it is saving
spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[spinner startAnimating];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinner];

dispatch_async(appendQueue, ^{
....my code....

ここまたは下でスピナーを終了できます。

    [self performSelectorOnMainThread:@selector(doneWithSave:)
                           withObject:sender waitUntilDone:YES];
});
dispatch_release(appendQueue);

}

  • (void) doneWithSave:(id) ボタン { self.navigationItem.rightBarButtonItem = ボタン; [self.navigationController popToRootViewControllerAnimated:TRUE]; }
于 2012-10-21T14:34:12.887 に答える
1

実際にボタンを有効または無効にする代わりに、内部ブール変数を true または false に設定します。次に、ボタンが押されたときに実行されるコードは、その変数をチェックして、ボタンの押しを無視するか、実際に何かを行うかを決定します。

于 2012-10-21T14:36:29.580 に答える
-1

これらのコードも使用できます

[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];

アニメーションが開始すると、このアニメーションが完了した後に beginIgnoringInteractionEvents と endIgnoringInteractionEvents を実行できます

于 2014-12-18T06:41:57.607 に答える