I'm having two crossfading view controllers both of which play video in their subviews. The video in view A starts playing when the fade-in starts and stops when the fadeout finishes. The video in view B starts on fade-in and stops after fade-out. Basic stuff. I made it work fine with MPMoviePlayerController but i also wanted to do audio fade in/out which forced me to go with the AVPlayer from AVFoundationFramework. Basically everything seemed to work fine but i noticed that the switch caused the fade-in to break. The view B alpha just jumps from 0 to 1 and the completition block of UIView animateWithDuration gets called with false value. I noticed that this only happens when the i call the replaceCurrentItemWithPlayerItem: method on AVPlayer object during loadView method.
The crossfading code looks like this:
- (void)pushViewController:(UIViewController *)viewController duration:(float)duration
{
float halfFadeInOutTime = duration/2.0;
viewController.view.alpha = 0.0;
UIView *tmpView = self.view;
[viewController viewWillAppear:YES];
//start fading out the first view
[UIView animateWithDuration:halfFadeInOutTime
delay:0
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction
animations:^{
tmpView.alpha = 0.0;
}
completion:^(BOOL finished){
if( finished ){
if( [self respondsToSelector:@selector(fadeOutFinished:)] ){
[self fadeOutFinished:duration];
}
[self.navigationController pushViewController:viewController animated:NO];
//start fading in with the second view
[UIView animateWithDuration:halfFadeInOutTime
delay:0
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction
animations:^{
viewController.view.alpha = 1.0;
}
completion:^(BOOL finished2){
if( finished2 ){
if( [((CrossfadeableViewController*)viewController) respondsToSelector:@selector(fadeInFinished:)] ){
[((CrossfadeableViewController*)viewController) fadeInFinished:duration];
}
}
}
];
if( [((CrossfadeableViewController*)viewController) respondsToSelector:@selector(fadeInStarted:)] ){
[((CrossfadeableViewController*)viewController) fadeInStarted:duration];
}
}
}
];
if( [self respondsToSelector:@selector(fadeOutStarted:)] ){
[self fadeOutStarted:duration];
}
}
The AVPlayer related code in loadView looks like this
- (void) loadView
{
[super loadView]
//...
/*
* Variables of type:
* UIView *videoPlaceholder;
* AVURLAsset *asset;
* AVPlayerItem *playerItem;
* AVPlayer *player;
* AVPlayerLayer *playerLayer;
*/
videoPlaceholder = [[UIView alloc] initWithFrame:_frame];
playerLayer = [[AVPlayerLayer alloc] init];
[playerLayer setFrame:videoPlaceholder.frame];
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
player = [[AVPlayer alloc] init];
NSString *_url = [[NSBundle mainBundle] pathForResource:[_videoFilename stringByDeletingPathExtension] ofType:[_videoFilename pathExtension]];
if( _url != nil ){
NSURL *url = [NSURL fileURLWithPath:_url];
asset = [AVURLAsset URLAssetWithURL:url options:nil];
playerItem = [AVPlayerItem playerItemWithAsset:asset];
[player replaceCurrentItemWithPlayerItem:playerItem];
[player seekToTime:kCMTimeZero];
[player setActionAtItemEnd:AVPlayerActionAtItemEndNone];
}
playerLayer.player = player;
[videoPlaceholder.layer addSublayer:playerLayer];
[self.view addSubview:videoPlaceholder];
//....
}
Does anyone know what can cause breaking of the animation? I'm not changing anything in the views during aniation since loadView gets called before the crossfade starts. And what can cause the same code to work with MPMoviePlayerController and breaks with AVPlayer?
Cheers, PB