programing

애니메이션 DidStop에서 CA 애니메이션을 식별하는 방법은 무엇입니까?

telecom 2023. 7. 14. 23:40
반응형

애니메이션 DidStop에서 CA 애니메이션을 식별하는 방법은 무엇입니까?

일련의 CAT 전환/CA 애니메이션 시퀀스가 중복되는 문제가 있었습니다. 애니메이션이 중지되면 모든 작업을 사용자 지정 작업을 수행해야 했지만 애니메이션 DidStop에 대한 대리 처리기를 한 명만 원했습니다.

하지만 문제가 있었습니다. 애니메이션 DidStop 대리인에서 각 CAT 전환/CA 애니메이션을 고유하게 식별할 수 있는 방법이 없는 것 같습니다.

저는 CAA 애니메이션의 일부로 노출된 키/값 시스템을 통해 이 문제를 해결했습니다.

애니메이션을 시작할 때 CAT 전환/CA 애니메이션에서 setValue 메서드를 사용하여 animationDidStop이 실행될 때 사용할 식별자와 값을 설정합니다.

-(void)volumeControlFadeToOrange
{   
    CATransition* volumeControlAnimation = [CATransition animation];
    [volumeControlAnimation setType:kCATransitionFade];
    [volumeControlAnimation setSubtype:kCATransitionFromTop];
    [volumeControlAnimation setDelegate:self];
    [volumeControlLevel setBackgroundImage:[UIImage imageNamed:@"SpecialVolume1.png"] forState:UIControlStateNormal];
    volumeControlLevel.enabled = true;
    [volumeControlAnimation setDuration:0.7];
    [volumeControlAnimation setValue:@"Special1" forKey:@"MyAnimationType"];
    [[volumeControlLevel layer] addAnimation:volumeControlAnimation forKey:nil];    
}

- (void)throbUp
{
    doThrobUp = true;

    CATransition *animation = [CATransition animation]; 
    [animation setType:kCATransitionFade];
    [animation setSubtype:kCATransitionFromTop];
    [animation setDelegate:self];
    [hearingAidHalo setBackgroundImage:[UIImage imageNamed:@"m13_grayglow.png"] forState:UIControlStateNormal];
    [animation setDuration:2.0];
    [animation setValue:@"Throb" forKey:@"MyAnimationType"];
    [[hearingAidHalo layer] addAnimation:animation forKey:nil];
}

애니메이션에서 DidStop 대리인:

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag{

    NSString* value = [theAnimation valueForKey:@"MyAnimationType"];
    if ([value isEqualToString:@"Throb"])
    {
       //... Your code here ...
       return;
    }


    if ([value isEqualToString:@"Special1"])
    {
       //... Your code here ...
       return;
    }

    //Add any future keyed animation operations when the animations are stopped.
 }

또 다른 측면은 키 값 쌍 시스템을 대리자 클래스에 저장할 필요 없이 키 값 쌍 시스템의 상태를 유지할 수 있다는 것입니다.코드는 적을수록 좋습니다.

코딩에 대한 Apple Reference를 반드시 확인하십시오.

애니메이션 DidStop에서 CA 애니메이션/CAT 전환 식별을 위한 더 나은 기법이 있습니까?

감사합니다. --배터

배트가의 기술은 너무 복잡합니다.addAnimation의 forKey 매개 변수를 활용하는 것은 어떻습니까?그것은 바로 이 목적을 위해 만들어졌습니다.setValue 호출을 꺼내고 키 문자열을 addAnimation 호출로 이동하기만 하면 됩니다.예:

[[hearingAidHalo layer] addAnimation:animation forKey:@"Throb"];

그런 다음 애니메이션 DidStop 콜백에서 다음과 같은 작업을 수행할 수 있습니다.

if (theAnimation == [[hearingAidHalo layer] animationForKey:@"Throb"]) ...

저는 방금 CAA 애니메이션을 위한 완료 코드를 수행하는 훨씬 더 나은 방법을 생각해냈습니다.

블록에 대한 typeef를 만들었습니다.

typedef void (^animationCompletionBlock)(void);

애니메이션에 블록을 추가하는 데 사용하는 키:

#define kAnimationCompletionBlock @"animationCompletionBlock"

그런 다음 CA 애니메이션이 완료된 후 애니메이션 완료 코드를 실행하려면 자신을 애니메이션의 대리자로 설정하고 setValue:forKey:를 사용하여 애니메이션에 코드 블록을 추가합니다.

animationCompletionBlock theBlock = ^void(void)
{
  //Code to execute after the animation completes goes here    
};
[theAnimation setValue: theBlock forKey: kAnimationCompletionBlock];

그런 다음 지정된 키에서 블록을 확인하고 찾으면 실행하는 animationDidStop:finished:method를 구현합니다.

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
  animationCompletionBlock theBlock = [theAnimation valueForKey: kAnimationCompletionBlock];
  if (theBlock)
    theBlock();
}

이 접근 방식의 장점은 애니메이션 개체를 생성하는 동일한 위치에 정리 코드를 작성할 수 있다는 것입니다.더 좋은 것은 코드가 블록이기 때문에 코드가 정의된 범위의 로컬 변수에 액세스할 수 있다는 것입니다.userInfo 사전을 설치하는 데 어려움을 겪거나 다른 허튼소리를 할 필요가 없으며, 계속 성장하는 애니메이션 DidStop:finish: 다양한 종류의 애니메이션을 추가할수록 점점 더 복잡해지는 메소드를 작성할 필요가 없습니다.

사실, CA Animation에는 완료 블록 속성이 내장되어 있어야 하며 지정된 경우 자동으로 호출할 수 있는 시스템 지원이 있어야 합니다.그러나 위의 코드는 몇 줄의 추가 코드만으로 동일한 기능을 제공합니다.

다른 모든 대답들은 너무 복잡합니다!애니메이션을 식별하기 위해 자신만의 키를 추가하는 것이 어떻습니까?

이 솔루션은 매우 간단합니다. 필요한 것은 애니메이션에 자신의 키를 추가하는 것입니다(애니메이션).이 예에서는 ID)

이 줄을 삽입하여 애니메이션1을 식별합니다.

[myAnimation1 setValue:@"animation1" forKey:@"animationID"];

애니메이션 2를 식별하기 위한 것입니다.

[myAnimation2 setValue:@"animation2" forKey:@"animationID"];

다음과 같이 테스트합니다.

- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag
{
    if([[animation valueForKey:@"animationID"] isEqual:@"animation1"]) {
    //animation is animation1

    } else if([[animation valueForKey:@"animationID"] isEqual:@"animation2"]) {
    //animation is animation2

    } else {
    //something else
    }
}

인스턴스 변수는 필요하지 않습니다.

두 번째 접근 방식은 애니메이션을 실행하기 전에 애니메이션이 완료될 때 제거되지 않도록 명시적으로 설정한 경우에만 작동합니다.

CAAnimation *anim = ...
anim.removedOnCompletion = NO;

그렇지 않으면 애니메이션이 완료되기 전에 제거되고 콜백이 사전에서 찾지 못합니다.

위에서 암시한 내용(그리고 몇 시간 동안 허비한 후에 저를 여기에 오게 한 이유)을 명시하려면: 할당한 원래 애니메이션 개체가 다시 사용자에게 전달되는 것을 기대하지 마십시오.

 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)flag 

, 애메이끝나면면, 하왜냐이.[CALayer addAnimation:forKey:]애니메이션의 복사본을 만듭니다.

수 키이 " " "와 값(등가는 으로 여전히 입니다.animationDidStop:finished:상태를 할 수 있는 범위를 수 있습니다위에서 언급한 것처럼 KVC를 사용하면 상태를 저장하고 검색할 수 있는 충분한 범위를 얻을 수 있습니다.

저는 대부분의 objc 답변을 볼 수 있습니다. 위의 가장 좋은 답변을 바탕으로 빠른 2.3을 위해 만들 것입니다.

우선 이러한 모든 키를 개인 구조물에 저장하여 안전하게 사용할 수 있도록 하는 것이 좋을 것이며 향후 변경할 경우 코드의 모든 곳에서 변경하는 것을 잊었다고 해서 성가신 버그가 발생하지는 않을 것입니다.

private struct AnimationKeys {
    static let animationType = "animationType"
    static let volumeControl = "volumeControl"
    static let throbUp = "throbUp"
}

보시다시피 변수/애니메이션의 이름을 변경했으므로 더 명확합니다.이제 애니메이션을 만들 때 이 키를 설정합니다.

volumeControlAnimation.setValue(AnimationKeys.volumeControl, forKey: AnimationKeys.animationType)

(...)

throbUpAnimation.setValue(AnimationKeys.throbUp, forKey: AnimationKeys.animationType)

마지막으로 애니메이션이 중지될 때 딜러를 처리합니다.

override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
    if let value = anim.valueForKey(AnimationKeys.animationType) as? String {
        if value == AnimationKeys.volumeControl {
            //Do volumeControl handling
        } else if value == AnimationKeys.throbUp {
            //Do throbUp handling
        }
    }
}

Xcode 9 스위프트 4.0

키 값을 사용하여 애니메이션 DidStop 대리자 메서드에서 반환된 애니메이션에 추가한 애니메이션을 연결할 수 있습니다.

모든 활성 애니메이션 및 관련 완료를 포함하도록 사전을 선언합니다.

 var animationId: Int = 1
 var animating: [Int : () -> Void] = [:]

애니메이션을 추가할 때 키를 설정합니다.

moveAndResizeAnimation.setValue(animationId, forKey: "CompletionId")
animating[animationId] = {
    print("completion of moveAndResize animation")
}
animationId += 1    

애니메이션 DidStop에서는 마법이 발생합니다.

    let animObject = anim as NSObject
    if let keyValue = animObject.value(forKey: "CompletionId") as? Int {
        if let completion = animating.removeValue(forKey: keyValue) {
            completion()
        }
    }

Apple의 키 값을 사용하는 IMHO는 애플리케이션별 데이터를 객체에 추가할 수 있도록 하는 우아한 방법입니다.

애니메이션 개체에 대한 참조를 저장하고 포인터 비교를 수행하여 개체를 식별할 수도 있습니다.

2개의 CABasic Animation 객체가 동일한 애니메이션인지 확인하기 위해 keyPath 함수를 사용하여 동일한 작업을 수행합니다.

if([substant]A keyPath] == [애니메이션B keyPath])

  • CABasic Animation은 더 이상 애니메이션이 아니므로 KeyPath를 설정할 필요가 없습니다.

나는 사용하기를 좋아합니다.setValue:forKey동일한 종류의 애니메이션을 다른 레이어에 추가할 수 있기 때문에 ID를 기반으로 애니메이션을 고유하게 식별하는 것보다 애니메이션 보기를 계속 참조하는 것이 안전합니다.

이 두 가지는 동일합니다.

[UIView animateWithDuration: 0.35
                 animations: ^{
                     myLabel.alpha = 0;
                 } completion: ^(BOOL finished) {
                     [myLabel removeFromSuperview];
                 }];

이것으로:

CABasicAnimation *fadeOut = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeOut.fromValue = @([myLabel.layer opacity]);
fadeOut.toValue = @(0.0);
fadeOut.duration = 0.35;
fadeOut.fillMode = kCAFillModeForwards;
[fadeOut setValue:myLabel forKey:@"item"]; // Keep a reference to myLabel
fadeOut.delegate = self;
[myLabel.layer addAnimation:fadeOut forKey:@"fadeOut"];
myLabel.layer.opacity = 0;

그리고 대리인 방법으로:

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    id item = [anim valueForKey:@"item"];

    if ([item isKindOfClass:[UIView class]])
    {
        // Here you can identify the view by tag, class type 
        // or simply compare it with a member object

        [(UIView *)item removeFromSuperview];
    }
}

언급URL : https://stackoverflow.com/questions/1255086/how-to-identify-caanimation-within-the-animationdidstop-delegate

반응형