我在UITableView中有多个视频。 我想做藤蔓的饲料。 滚动到视频时自动播放视频 我使用AVPlyer来做到这一点。 但是我发现当两个视频切换时它并不是那么顺利 谁能提出一些建议?
这是我的tableViewController的observeValueForKeyPath,我用它来做视频切换;
[oldCell cleanupMoviePlayer]会做一些干净的工作(用于清理视图删除一些观察者)
[(MOVideoPlayer_AVPlayer *)newItem startPlay]会做一些初始化和设置(设置AVPlayerItem并播放)
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
id newItem = [change objectForKey:NSKeyValueChangeNewKey];
id oldCell = [change objectForKey:NSKeyValueChangeOldKey];
if (oldCell == (id)[NSNull null]) {
} else if([oldCell isKindOfClass:[MOVideoPlayer_AVPlayer class]]) {
[oldCell cleanupMoviePlayer];
}
if ([newItem isKindOfClass:[MOVideoPlayer_AVPlayer class]]) {
[(MOVideoPlayer_AVPlayer*)newItem startPlay];
}
}
-(void) startPlay
{
willStartePlay = YES;
double delayInSeconds = 0.5;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.indicator startAnimating];
if (isClearnup) {
return;
}
NSString *videoFilePath =[NSString stringWithFormat:@"%@%@",NSTemporaryDirectory(),[self.post.video_url lastPathComponent]];
//NSLog(@"the videoFilePath is %@",videoFilePath);
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:videoFilePath]) {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:self.post.video_url]];
NSLog(@"post.video_url:%@",self.post.video_url);
downloadOperation = [[AFDownloadRequestOperation alloc] initWithRequest:request targetPath:videoFilePath shouldResume:NO];
[downloadOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([fileManager fileExistsAtPath:videoFilePath]) {
[self createAndPlayMovieForURL:[NSURL fileURLWithPath:videoFilePath] sourceType:MPMovieSourceTypeFile];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"the error is %@",error);
NSLog(@"%@",operation.description);
dispatch_async(dispatch_get_main_queue(), ^{
[self.indicator stopAnimating];
});
}];
[downloadOperation start];
} else {
[self createAndPlayMovieForURL:[NSURL fileURLWithPath:videoFilePath] sourceType:MPMovieSourceTypeFile];
}
});
}
-(void)createAndPlayMovieForURL:(NSURL *)movieURL sourceType:(MPMovieSourceType)sourceType
{
if (isClearnup) {
return;
}
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:movieURL options:nil];
NSArray *requestedKeys = [NSArray arrayWithObjects: kPlayableKey, nil];
[asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self prepareToPlayAsset:asset withKeys:requestedKeys];
});
}];
}
-(void)prepareToPlayAsset:(AVURLAsset *)asset withKeys:(NSArray *)requestedKeys
{
if (isClearnup) {
return;
}
for (NSString *thisKey in requestedKeys)
{
NSError *error = nil;
AVKeyValueStatus keyStatus = [asset statusOfValueForKey:thisKey error:&error];
if (keyStatus == AVKeyValueStatusFailed)
{
return;
}
}
if (!asset.playable) {
return;
}
if (self.currentPlayerItem) {
[self.currentPlayerItem removeObserver:self forKeyPath:kStatusKey context:MOAVPlayerStatusObservationContext];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.currentPlayerItem];
}
self.currentPlayerItem = [AVPlayerItem playerItemWithAsset:asset];
[self.currentPlayerItem addObserver:self
forKeyPath:kStatusKey
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:MOAVPlayerStatusObservationContext];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.currentPlayerItem];
if (!self.player) {
self.player = [AVPlayer playerWithPlayerItem:self.currentPlayerItem];
[self.player addObserver:self
forKeyPath:kCurrentItemKey
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:MOAVPlayerCurrentItemObservationContext];
/* Observe the AVPlayer "rate" property to update the scrubber control. */
[self.player addObserver:self
forKeyPath:kRateKey
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:MOAVPlayerRateObservationContext];
}
if (self.player.currentItem != self.currentPlayerItem) {
[self.player replaceCurrentItemWithPlayerItem:self.currentPlayerItem];
}
}
-(void)playerItemDidReachEnd:(NSNotification*)notication
{
[self.player seekToTime:kCMTimeZero];
[self.player play];
}
-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == MOAVPlayerStatusObservationContext) {
AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
switch (status) {
case AVPlayerStatusUnknown:
{
//NSLog(@"AVPlayerStatusUnknown");
}
break;
case AVPlayerStatusReadyToPlay:
{
NSLog(@"AVPlayerStatusReadyToPlay");
[self.player play];
}
break;
case AVPlayerStatusFailed:
{
//NSLog(@"AVPlayerStatusFailed");
}
break;
}
} else if (context == MOAVPlayerRateObservationContext) {
//NSLog(@"MOAVPlayerRateObservationContext");
} else if (context == MOAVPlayerCurrentItemObservationContext){
// NSLog(@"CurrentItem change");
AVPlayerItem *newPlayerItem = [change objectForKey:NSKeyValueChangeNewKey];
if(newPlayerItem == (id)[NSNull null]){
// newPlayeritem is null?
//NSLog(@"newPlayerItem IS null");
} else {
//self.playerView.frame = self.backgroundImageView.frame;
//[self addSubview:self.playerView];
if (isClearnup) {
return;
}
isStartePlay = YES;
double delayInSeconds = 0.2;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//self.playerView.player = self.player;
[self.indicator stopAnimating];
//[self.playerView setVideoFillMode:AVLayerVideoGravityResizeAspect];
//dispatch_async(dispatch_get_main_queue(), ^{
// [self.player play];
self.playerView.player = self.player;
//});
//
});
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
-(void)cleanupMoviePlayerView
{
//[self.playerView removeFromSuperview];
self.playerView.player = nil;
//[self.moviePlayer.view removeFromSuperview];
//[self.maskView removeFromSuperview];
}
-(void)handleTap:(UITapGestureRecognizer*)tapGestureRecognizer;
{
if (interrupted) {
return;
}
// NSLog(@"tapGestureRecognizer");
if (isplaying) {
[self.moviePlayer pause];
} else {
[self.moviePlayer play];
}
}
// Remove the movie notification observers from the movie object.
-(void)removeMovieNotificationHandlers
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void) cleanupMoviePlayer
{
if (willStartePlay && isStartePlay) {
[self.player seekToTime:kCMTimeZero];
//[self.moviePlayer stop];
[self cleanupMoviePlayerView];
[self removeMovieNotificationHandlers];
}
isClearnup = YES;
}
-(void)prepareForReuse
{
willStartePlay = isStartePlay = isClearnup = NO;
}
-(void) startPlay
{
willStartePlay = YES;
double delayInSeconds = 0.5;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.indicator startAnimating];
if (isClearnup) {
return;
}
NSString *videoFilePath =[NSString stringWithFormat:@"%@%@",NSTemporaryDirectory(),[self.post.video_url lastPathComponent]];
//NSLog(@"the videoFilePath is %@",videoFilePath);
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:videoFilePath]) {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:self.post.video_url]];
NSLog(@"post.video_url:%@",self.post.video_url);
downloadOperation = [[AFDownloadRequestOperation alloc] initWithRequest:request targetPath:videoFilePath shouldResume:NO];
[downloadOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([fileManager fileExistsAtPath:videoFilePath]) {
[self createAndPlayMovieForURL:[NSURL fileURLWithPath:videoFilePath] sourceType:MPMovieSourceTypeFile];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"the error is %@",error);
NSLog(@"%@",operation.description);
dispatch_async(dispatch_get_main_queue(), ^{
[self.indicator stopAnimating];
});
}];
[downloadOperation start];
} else {
[self createAndPlayMovieForURL:[NSURL fileURLWithPath:videoFilePath] sourceType:MPMovieSourceTypeFile];
}
});
}
-(void)createAndPlayMovieForURL:(NSURL *)movieURL sourceType:(MPMovieSourceType)sourceType
{
if (isClearnup) {
return;
}
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:movieURL options:nil];
NSArray *requestedKeys = [NSArray arrayWithObjects: kPlayableKey, nil];
[asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self prepareToPlayAsset:asset withKeys:requestedKeys];
});
}];
}
-(void)prepareToPlayAsset:(AVURLAsset *)asset withKeys:(NSArray *)requestedKeys
{
if (isClearnup) {
return;
}
for (NSString *thisKey in requestedKeys)
{
NSError *error = nil;
AVKeyValueStatus keyStatus = [asset statusOfValueForKey:thisKey error:&error];
if (keyStatus == AVKeyValueStatusFailed)
{
return;
}
}
if (!asset.playable) {
return;
}
if (self.currentPlayerItem) {
[self.currentPlayerItem removeObserver:self forKeyPath:kStatusKey context:MOAVPlayerStatusObservationContext];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.currentPlayerItem];
}
self.currentPlayerItem = [AVPlayerItem playerItemWithAsset:asset];
[self.currentPlayerItem addObserver:self
forKeyPath:kStatusKey
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:MOAVPlayerStatusObservationContext];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.currentPlayerItem];
if (!self.player) {
self.player = [AVPlayer playerWithPlayerItem:self.currentPlayerItem];
[self.player addObserver:self
forKeyPath:kCurrentItemKey
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:MOAVPlayerCurrentItemObservationContext];
/* Observe the AVPlayer "rate" property to update the scrubber control. */
[self.player addObserver:self
forKeyPath:kRateKey
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:MOAVPlayerRateObservationContext];
}
if (self.player.currentItem != self.currentPlayerItem) {
[self.player replaceCurrentItemWithPlayerItem:self.currentPlayerItem];
}
}
-(void)playerItemDidReachEnd:(NSNotification*)notication
{
[self.player seekToTime:kCMTimeZero];
[self.player play];
}
-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == MOAVPlayerStatusObservationContext) {
AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
switch (status) {
case AVPlayerStatusUnknown:
{
//NSLog(@"AVPlayerStatusUnknown");
}
break;
case AVPlayerStatusReadyToPlay:
{
NSLog(@"AVPlayerStatusReadyToPlay");
[self.player play];
}
break;
case AVPlayerStatusFailed:
{
//NSLog(@"AVPlayerStatusFailed");
}
break;
}
} else if (context == MOAVPlayerRateObservationContext) {
//NSLog(@"MOAVPlayerRateObservationContext");
} else if (context == MOAVPlayerCurrentItemObservationContext){
// NSLog(@"CurrentItem change");
AVPlayerItem *newPlayerItem = [change objectForKey:NSKeyValueChangeNewKey];
if(newPlayerItem == (id)[NSNull null]){
// newPlayeritem is null?
//NSLog(@"newPlayerItem IS null");
} else {
//self.playerView.frame = self.backgroundImageView.frame;
//[self addSubview:self.playerView];
if (isClearnup) {
return;
}
isStartePlay = YES;
double delayInSeconds = 0.2;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
//self.playerView.player = self.player;
[self.indicator stopAnimating];
//[self.playerView setVideoFillMode:AVLayerVideoGravityResizeAspect];
//dispatch_async(dispatch_get_main_queue(), ^{
// [self.player play];
self.playerView.player = self.player;
//});
//
});
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
-(void)cleanupMoviePlayerView
{
//[self.playerView removeFromSuperview];
self.playerView.player = nil;
//[self.moviePlayer.view removeFromSuperview];
//[self.maskView removeFromSuperview];
}
-(void)handleTap:(UITapGestureRecognizer*)tapGestureRecognizer;
{
if (interrupted) {
return;
}
// NSLog(@"tapGestureRecognizer");
if (isplaying) {
[self.moviePlayer pause];
} else {
[self.moviePlayer play];
}
}
// Remove the movie notification observers from the movie object.
-(void)removeMovieNotificationHandlers
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void) cleanupMoviePlayer
{
if (willStartePlay && isStartePlay) {
[self.player seekToTime:kCMTimeZero];
//[self.moviePlayer stop];
[self cleanupMoviePlayerView];
[self removeMovieNotificationHandlers];
}
isClearnup = YES;
}
-(void)prepareForReuse
{
willStartePlay = isStartePlay = isClearnup = NO;
}