1

私はUIGraphicsコンテキストが苦手なので、ここで何が起こっているのかを助けたり説明したりできることを願っています。

ビュー コントローラーのプライマリ ビューの指定されたスペースに対してラベル テキストが長すぎる場合に、フレーム内でラベルを自動的に前後にスクロールするクラスを定義しました。

親ビューに割り当てられたスペースに収まるスクロールビューで構成され、UILabelテキストに合わせてサイズ変更された (サブクラス化された) が含まれています。(UILabel は親スクロールビューのサブビューです)。

scrollview は、UILabel を左 -> 右にスクロールするアニメーションをコミットし、アニメーションが終了したら、デリゲートを起動します '

(void)animationDidStop:animationID(NSString*)finished:(NSNumber *)finished context:(void *)context' 

いくつかの数字をリセットし、逆方向にスクロールしてアニメーションを再開しました - >左

これは本当にうまく機能します。

ただし、この「スクロール ラベル」の別のインスタンスをビュー コントローラーのマスター ビューの別の場所に追加すると、アニメーションの 1 つが停止し、AnimationDidStopデリゲートが起動されると、他の「スクロール」ラベル オブジェクトのアニメーションが最初から再起動されます。

アニメーションの発火を分離するために次のことを試みましたが、肯定的な結果は得られませんでした。ビューのコンテキストと識別子を beginAnimations に渡し、それらを(void)animationDidStopメソッドにトラップします...違いはありませんでした。これは、メソッドがかからないように思われます

以下は、アニメーションを実行するコードと、アニメーションを別の方向に再起動するコードです。

私が言うように、それはそれ自体で非常にうまく機能しますが、同時に画面上に常駐するこのクラスの複数のインスタンスがある場合、beginAnimations は両方のインスタンスに対して起動するようです。

理由を説明していただければ幸いです。ありがとう。

- (void)beginAnimationWithOrgigin:(CGPoint)origin Terminus:(CGPoint)terminus {


NSLog (@"Message %@ in context %@",((UILabel*)_textLabel).text,_ctx);

CGFloat text_width = ((UILabel*)_textLabel).frame.size.width;
CGFloat display_width = self.frame.size.width;

if ( text_width > display_width ) {
    float duration = (text_width - display_width)/40;
    [self setContentOffset:origin];

    [UIView beginAnimations:((UILabel*)_textLabel).text context:_ctx];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDelay:1.0];
    [UIView setAnimationDuration:duration];
    [UIView setAnimationRepeatCount:1];
    [self setContentOffset:terminus];

    [UIView commitAnimations];

}
}


- (void)animationDidStop:(NSString *)animationID
            finished:(NSNumber *)finished
             context:(void *)context
{

NSLog(@"Animation Did stop context = %@",context);

if ([animationID isEqualToString:((UILabel*)_textLabel).text]){

    static BOOL forward = NO;
    if ([finished boolValue]) {

        CGPoint origin;
        CGPoint terminal_origin;

        if (forward){
            origin = CGPointMake(0, 0);
            terminal_origin = CGPointMake(((UILabel*)_textLabel).frame.size.width - self.frame.size.width, ((UILabel*)_textLabel).frame.origin.y);
        }else{

            terminal_origin = CGPointMake(0, 0);
            origin = CGPointMake(((UILabel*)_textLabel).frame.size.width - self.frame.size.width, ((UILabel*)_textLabel).frame.origin.y);
        }

        forward = !forward;
        [self beginAnimationWithOrgigin:origin Terminus:terminal_origin];
    }
}
}

編集: 追加 28/5/14 @ 13:14 A-Lives がスタティックの使用に関するアドバイスをした後... コードを変更して、そのラベルをフラグとして使用し、スクロールの方向の変更を促すようにしました。これで問題は解決しました

- (void)beginAnimationWithOrgigin:(CGPoint)origin Terminus:(CGPoint)terminus Direction:(NSString*)direction{

if (!direction)direction = @"FORWARD";

NSLog (@"Message %@ in context %@",((UILabel*)_textLabel).text,_ctx);

CGFloat text_width = ((UILabel*)_textLabel).frame.size.width;
CGFloat display_width = self.frame.size.width;

if ( text_width > display_width ) {
    float duration = (text_width - display_width)/40;
    [self setContentOffset:origin];

    [UIView beginAnimations:direction context:_ctx];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDelay:1.0];
    [UIView setAnimationDuration:duration];
    [UIView setAnimationRepeatCount:1];
    [self setContentOffset:terminus];

    [UIView commitAnimations];

}
}



- (void)animationDidStop:(NSString *)animationID
            finished:(NSNumber *)finished
             context:(void *)context
{

NSLog(@"Animation Did stop context = %@",context);
NSString *direction;
CGPoint origin;
CGPoint terminal_origin;

    if (![animationID isEqualToString:@"FORWARD"]){
        origin = CGPointMake(0, 0);
        terminal_origin = CGPointMake(((UILabel*)_textLabel).frame.size.width - self.frame.size.width, ((UILabel*)_textLabel).frame.origin.y);
        direction = @"FORWARD";
    }else{

        terminal_origin = CGPointMake(0, 0);
        origin = CGPointMake(((UILabel*)_textLabel).frame.size.width - self.frame.size.width, ((UILabel*)_textLabel).frame.origin.y);
        direction = @"BACKWARD";
        }

[self beginAnimationWithOrgigin:origin Terminus:terminal_origin Direction:direction];
}
4

1 に答える 1

0

問題は、静的変数が実際には、アプリ全体でグローバルにアクセスできる通常の C 静的変数であることを忘れていたことです。(つまり、それらを定義したスコープにカプセル化されていません。)

同じクラスの複数のインスタンスはすべて、同じ変数に対して値を読み書きしているため、予期しない動作が発生します。

解決策: インスタンス レベルのメッセージを渡して、クラスがシングルトンであることを保証できないトグル アクティビティを制御します。

変更された作業コード:

- (void)beginAnimationWithOrgigin:(CGPoint)origin Terminus:(CGPoint)terminus Direction:(NSString*)direction{

    if (!direction)direction = @"FORWARD";

    NSLog (@"Message %@ in context %@",((UILabel*)_textLabel).text,_ctx);

    CGFloat text_width = ((UILabel*)_textLabel).frame.size.width;
    CGFloat display_width = self.frame.size.width;

    if ( text_width > display_width ) {
        float duration = (text_width - display_width)/40;
        [self setContentOffset:origin];

        [UIView beginAnimations:direction context:_ctx];
        [UIView setAnimationDelegate:self];
        [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
        [UIView setAnimationDelay:1.0];
        [UIView setAnimationDuration:duration];
        [UIView setAnimationRepeatCount:1];
        [self setContentOffset:terminus];

        [UIView commitAnimations];

    }
}



- (void)animationDidStop:(NSString *)animationID
        finished:(NSNumber *)finished
         context:(void *)context
{

    NSLog(@"Animation Did stop context = %@",context);
    NSString *direction;
    CGPoint origin;
    CGPoint terminal_origin;

    if (![animationID isEqualToString:@"FORWARD"]){
        origin = CGPointMake(0, 0);
        terminal_origin = CGPointMake(((UILabel*)_textLabel).frame.size.width - self.frame.size.width, ((UILabel*)_textLabel).frame.origin.y);
        direction = @"FORWARD";
    }else{

        terminal_origin = CGPointMake(0, 0);
        origin = CGPointMake(((UILabel*)_textLabel).frame.size.width - self.frame.size.width, ((UILabel*)_textLabel).frame.origin.y);
        direction = @"BACKWARD";
        }

    [self beginAnimationWithOrgigin:origin Terminus:terminal_origin Direction:direction];
}
于 2014-04-28T20:28:12.590 に答える