1

をオーバーライドするカスタムセルを含むテーブルビューがありますsetSelected:animated:。選択されたセルを含むテーブルをスクロールすると、選択されたセルの外観が、選択された状態と選択されていない状態の奇妙な組み合わせになることがあります。

私のsetSelected:animated:方法は次のようになります。

-(void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    if (selected == self.selected)
        return;

    CGFloat destinationAlpha = selected ? 1.0 : 0.0;
    NSTimeInterval duration = animated ? 0.25 : 0.0;

    for (UIView *view in self.topView.subviews)
    {
        if (![self.viewsToLeaveBackgroundAlone containsObject:view])
            view.backgroundColor = [UIColor clearColor];
    }

    [UIView animateWithDuration:duration animations:^{
        self.selectedTopViewBackground.alpha = destinationAlpha;
    }animations completion:^(BOOL finished) {
        if (!selected)
        {
            for (UIView *view in self.topView.subviews)
            {
                if (![self.viewsToLeaveBackgroundAlone containsObject:view])
                    view.backgroundColor = self.topView.backgroundColor;
            }
        }        
    }];

    [super setSelected:selected animated:animated];
}

ログとブレークポイントを追加しました。右のセルに正しい選択状態が送信されています。何がうまくいかないのですか?

4

1 に答える 1

0

持続時間がゼロのアニメーションの完了ブロックがすぐに呼び出されることに依存できないことがわかりました。私のテストから、完成したパラメーターは常にYES同様です。

アニメーション化されていないトランジションの継続時間をゼロに設定することは非常に魅力的ですが、アニメーションに完了ブロックが含まれていて、メソッドが立て続けに呼び出される場合、完了ブロックの順序を保証することはできません。呼ばれた。

たとえば、テーブルを上下にスクロールしているときに、次のことが発生する可能性があります。

  • 選択したセルが画面外にスクロールされ、再利用されます (選択:NO アニメーション:NO)
  • 選択されたセルが画面にスクロールバックされます (選択:YES アニメーション:NO)

長さゼロのアニメーションを使用しても、最初の呼び出しの完了ブロックが 2 番目の呼び出しの完了ブロックの前に呼び出されるとは限りません。

animated解決策は、アニメーション操作と完了操作を 2 つのローカル ブロックでラップし、パラメーターに応じてこれらを直接実行するか、アニメーションに渡すことです。

-(void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    if (selected == self.selected)
        return;

    CGFloat destinationAlpha = selected ? 1.0 : 0.0;

    for (UIView *view in self.topView.subviews)
    {
        if (![self.viewsToLeaveBackgroundAlone containsObject:view])
            view.backgroundColor = [UIColor clearColor];
    }

    dispatch_block_t animations = ^{
        self.selectedTopViewBackground.alpha = destinationAlpha;
    };

    dispatch_block_t completion = ^{
        if (!selected)
        {
            for (UIView *view in self.topView.subviews)
            {
                if (![self.viewsToLeaveBackgroundAlone containsObject:view])
                    view.backgroundColor = self.topView.backgroundColor;
            }
        }
    };

    if (animated)
    {
        [UIView animateWithDuration:0.25 animations:animations completion:^(BOOL finished) { completion();}];
    }
    else
    {
        animations();
        completion();
    }
    [super setSelected:selected animated:animated];
}

これには、2 つの巨大なコード ブロックを含む 1 つの大規模な呼び出しがないという追加の利点があります (より複雑なケースの場合)。ネストされたアニメーションがある場合はなおさらです。

于 2013-06-05T15:42:45.207 に答える