Languages/Objective-C2011.01.04 16:19
[이전 글에 이어서..]

그럼 새로운 UIView 애니메이션은 어떻게 써먹느냐. Ruby 같은 프로그래밍 언어를 보면 함수를 실행할 때 그 함수에 다른 함수 바디를 동적으로 만들어서 넘길 수도 있도록 허용하고 있는데요. Objective-C에서도 이제 그런 식의 프로그래밍이 가능합니다. 우선 developer.apple.com에서 퍼온 API 설명부터 한번 보죠.

animateWithDuration:animations:completion:

Animate changes to one or more views using the specified duration and completion handler.

+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
Parameters
duration

The total duration of the animations, measured in seconds. If you specify a negative value or 0, the changes are made without animating them.

animations

A block object containing the changes to commit to the views. This is where you programmatically change any animatable properties of the views in your view hierarchy. This block takes no parameters and has no return value. This parameter must not be NULL.

completion

A block object to be executed when the animation sequence ends. This block has no return value and takes a single Boolean argument that indicates whether or not the animations actually finished before the completion handler was called. If the duration of the animation is 0, this block is performed at the beginning of the next run loop cycle. This parameter may be NULL.

Discussion

This method performs the specified animations immediately using the UIViewAnimationOptionCurveEaseInOut and UIViewAnimationOptionTransitionNone animation options.

For example, if you want to fade a view until it is totally transparent and then remove it from your view hierarchy, you could use code similar to the following:


이 함수는 static method이고, 첫 번째 인자로는 Animation 지속시간, 두 번째 인자로는 애니매이션이 수행되는 동안 행해질 작업에 대한 코드 블럭, 그리고 세 번째 인자로는 애니메이션이 끝나면 실행될 코드 블럭이 넘어갑니다.

대충 어떻게 써먹느냐 하면...

[UIView animatedWithDuration:0.2
            animations:^{view.alpha = 0.0;}
            completion:^(BOOL finished){ 
                               if ( finished)
                                  [view removeFromSuperView];
                             }];

위의 코드는 0.2 초 에 걸쳐, 어떤 뷰를 서서히 투명하게 만들고, 투명화 작업이 끝나면 그 뷰를 부모 뷰에서 떼 버리는 코드입니다. 블럭의 시작은 ^으로 표시하고, 인자의 목록은 () 안에, 블럭 코드 바디는 {} 안에 둔다는 것을 알 수 있습니다.

이렇게 코딩하면 앞서 봤던 [UIView beginAnimations], [UIView commitAnimations]를 통해 구현한 경우보다 코드 사이즈가 줄어듭니다. 애니메이션 종료시 호출될 메소드를 따로 구현해 둘 필요가 없거든요. 블럭 문법에 익숙한 분들에게는 코드도 훨씬 더 깔끔해 보이죠.



신고
Posted by 이병준

소중한 의견, 감사합니다. ^^

Languages/Objective-C2011.01.04 14:19

[UIView beginAnimation]

이거 써서 애니메이션 효과 넣으신 분들 많으시죠. iOS 4.0 부터는 블럭 기반 문법을 사용하는 API를 사용하도록 하라는 권고안이 날아오는 바람에 앞으로는 사용하기 좀 껄끄러워 질 것 같긴 합니다만, 그럼에도 여전히 많이 쓰이고 있습니다.
 
기본적으로 이 계열 API는 다음과 같이 사용하는데요.

gameCenter.frame = before;
[self.view addSubview:gameCenter];
[UIView beginAnimations:nil context:nil];
gameCenter.frame = after;
[UIView commitAnimations];


이렇게 하면 gameCenter의 프레임 위치가 움직이는 것이 애니메이션 형태로 표현되죠.

그런데 이렇게 프로그래밍 해 본 분들이면 대충 아시겠습니다만, commitAnimations 한 다음에 [gameCenter removeFromSuperview] 한다거나 [gameCenter release] 하면 애니메이션 효과가 제대로 먹질 않는 경우가 많아요. 애니메이션이 끝나기도 전에 뷰가 화면에서 사라지기 때문이죠.

이를 방지하기 위해서는 다음과 같이 해야 합니다.
(아마 대충 다 아시겠습니다만... ㅎ)

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(clearGameCenter)];
gameCenter.frame = after;
[UIView commitAnimations];
 
 
그러니까 애니메이션이 끝난 다음에 호출될 메소드와 그 메소드가 정의되어 있는 객체를 넘기는 것이죠. 후자의 작업은 setAnimationDelegate를 통해서 하고, 전자의 작업은 setAnimationDidStopSelector를 통해서 합니다.
 
그러니까 애니메이션이 끝난 다음에 gameCenter UIView를 화면에서 지워버리고 싶다면, clearGameCenter 메소드 안에서 다음과 같이 하면 됩니다.
 
- (void) clearGameCenter {
    [gameCenter removeFromSuperview];
    [gameCenter release];
    gameCenter = nil;
}
 
간단하죠. 이런 일들이 iOS 4.0 이상에서는 좀 더 간단해 질 터인데, 그에 관해서는 제가 XCode를 업그레이드 한 다음에 살펴보도록 하겠습니다. ㅎㅎ
 

[다음에 계속]


신고
Posted by 이병준

소중한 의견, 감사합니다. ^^