简体   繁体   English

AVPlayer replaceCurrentItemWithPlayerItem打破了UIViewAnimation

[英]AVPlayer replaceCurrentItemWithPlayerItem breaking UIViewAnimation

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. 视频A中的视频在淡入开始时开始播放,在淡出结束时停止播放。 The video in view B starts on fade-in and stops after fade-out. 视图B中的视频以淡入开始,淡出后停止。 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. 我用MPMoviePlayerController使它工作正常,但我也想做音频淡入/淡出,这迫使我从AVFoundationFramework转向AVPlayer。 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. 视图B alpha只是从0跳到1,UIView animateWithDuration的completition块被调用false值。 I noticed that this only happens when the i call the replaceCurrentItemWithPlayerItem: method on AVPlayer object during loadView method. 我注意到这只发生在我在loadView方法中调用AVPlayer对象上的replaceCurrentItemWithPlayerItem:方法时。

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 loadView中的AVPlayer相关代码如下所示

- (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. 我在aniation期间没有更改任何内容,因为在交叉淡入淡出开始之前调用loadView。 And what can cause the same code to work with MPMoviePlayerController and breaks with AVPlayer? 什么可以导致相同的代码与MPMoviePlayerController一起使用并打破AVPlayer?

Cheers, PB 干杯,PB

As it turns out it was an issue with the AVPlayerItem being loaded. 事实证明,加载AVPlayerItem是一个问题。 I had to wait until the movie got loaded - otherwise the animated fade in just broke 我不得不等到电影加载完毕 - 否则动画淡入就会破坏

the sample code for waiting until the video has done loading: 等待视频完成加载的示例代码:

- (void)observeValueForKeyPath:(NSString*) path 
                  ofObject:(id)object 
                    change:(NSDictionary*)change 
                   context:(void*)context {
  if (context == AVPlayerDemoPlaybackViewControllerStatusObservationContext) {
      AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
      if (status == AVPlayerStatusReadyToPlay) {
        if( [self.videoStateChangeDelegate respondsToSelector:@selector(videoStateChangedToReadyForPlayback)] ){
            [self.videoStateChangeDelegate videoStateChangedToReadyForPlayback];
        }
        [self.player play];
      }
  }
}

where the [self.videoStateChangeDelegate videoStateChangedToReadyForPlayback] notifies my delegate controller that it can start fading in. Too bad that my simple code got a little bit more complicated because of this issue. 其中[self.videoStateChangeDelegate videoStateChangedToReadyForPlayback]通知我的委托控制器它可以开始淡入。太糟糕了,因为这个问题我的简单代码变得有点复杂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM