停止AVPlayer并在缓存阶段立即播放其它视频闪退问题及解决方案

1.清除KVO;
2.暂停;
3.清空缓存区;
4.从父视图移除播放器;
5.移除播放器的全部视图;
6.把播放器置为nil。
具体代码:


-(void)hiddenPlayer
{
    if(self.isPlay && self.player)
    {
        [self.player.currentItem  removeObserver:self forKeyPath:@"status"];
        [self.player.currentItem  removeObserver:self forKeyPath:@"loadedTimeRanges"];
        [self.player pause];
        self.currentPlayerItem = nil;
        [self.player replaceCurrentItemWithPlayerItem:nil];//清除播放缓存
        for (CALayer *layer in self.photoImageView.layer.sublayers) {
            if ([layer class] == [AVPlayerLayer class]) {
                [layer removeFromSuperlayer];
            }
        }
        [self.player removeAllSubView];
        self.photoImageView.hidden = YES;
        self.isPlay = NO;
        self.player = nil;
//                [self.playButton setImage:[UIImage imageNamed:@"播放"] forState:UIControlStateNormal];
        [self updatePlayBtn];
    }
}

相关声明:

#import <AVFoundation/AVFoundation.h>

@interface PPChooseSongHeadView()<SDCycleScrollViewDelegate>
@property (nonatomic, strong) UILabel *describeTitleLabel;
@property (nonatomic, strong) UILabel *idLabel;
@property (nonatomic, strong) SDCycleScrollView *imagesScrollView;
@property (nonatomic, strong) UIView *backgroundView;
@property (nonatomic, strong) UIImageView *photoImageView;
@property (nonatomic, strong) UIButton *playButton;
@property (nonatomic, assign) BOOL isPlay;
@property (nonatomic, strong) JCTBannerEntity *entity;
@property (nonatomic,strong)AVPlayer *player;//播放器对象
@property (nonatomic,strong)AVPlayerItem *currentPlayerItem;
@end
@interface PPChooseSongHeadView : BGBaseView

//@property (nonatomic, strong) UILabel *backLabel;
@property (nonatomic, strong) JCTProjectListEntity *model;
@property (nonatomic, strong) PPRoomCateListEntity *roomCateListEntity;

@property (nonatomic, copy) void(^endEditingBlock)(void);

- (instancetype)initWithFrame:(CGRect)frame;

-(void)hiddenPlayer;

@end

视频建立与播放,按钮显示相关代码:

//2.添加属性观察
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
//    AVPlayerItem *playerItem = (AVPlayerItem *)object;
    if ([keyPath isEqualToString:@"status"]) {
        //获取playerItem的status属性最新的状态
        AVPlayerStatus status = [[change objectForKey:@"new"] intValue];
        switch (status) {
            case AVPlayerStatusReadyToPlay:{
//                //获取视频长度
//                CMTime duration = playerItem.duration;
//                //更新显示:视频总时长(自定义方法显示时间的格式)
//                self.totalNeedPlayTimeLabel.text = [self formatTimeWithTimeInterVal:CMTimeGetSeconds(duration)];
//                //开启滑块的滑动功能
//                self.sliderView.enabled = YES;
//                //关闭加载Loading提示
//                [self showaAtivityInDicatorView:NO];
                //开始播放视频
                [self.player play];
                break;
            }
            case AVPlayerStatusFailed:{//视频加载失败,点击重新加载
//                [self showaAtivityInDicatorView:NO];//关闭Loading视图
//                self.playerInfoButton.hidden = NO; //显示错误提示按钮,点击后重新加载视频
//                [self.playerInfoButton setTitle:@"资源加载失败,点击继续尝试加载" forState: UIControlStateNormal];
                [[BITNoticeView currentNotice] showErrorNotice:@"资源加载失败,请继续尝试加载"];
                [self hiddenPlayer];
                break;
            }
            case AVPlayerStatusUnknown:{
                NSLog(@"加载遇到未知问题:AVPlayerStatusUnknown");
                [self hiddenPlayer];
                break;
            }
            default:
                break;
        }
    } else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
//        //获取视频缓冲进度数组,这些缓冲的数组可能不是连续的
//        NSArray *loadedTimeRanges = playerItem.loadedTimeRanges;
//        //获取最新的缓冲区间
//        CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];
//        //缓冲区间的开始的时间
//        NSTimeInterval loadStartSeconds = CMTimeGetSeconds(timeRange.start);
//        //缓冲区间的时长
//        NSTimeInterval loadDurationSeconds = CMTimeGetSeconds(timeRange.duration);
//        //当前视频缓冲时间总长度
//        NSTimeInterval currentLoadTotalTime = loadStartSeconds + loadDurationSeconds;
//        //NSLog(@"开始缓冲:%f,缓冲时长:%f,总时间:%f", loadStartSeconds, loadDurationSeconds, currentLoadTotalTime);
//        //更新显示:当前缓冲总时长
//        _currentLoadTimeLabel.text = [self formatTimeWithTimeInterVal:currentLoadTotalTime];
//        //更新显示:视频的总时长
//        _totalNeedLoadTimeLabel.text = [self formatTimeWithTimeInterVal:CMTimeGetSeconds(self.player.currentItem.duration)];
//        //更新显示:缓冲进度条的值
//        _progressView.progress = currentLoadTotalTime/CMTimeGetSeconds(self.player.currentItem.duration);
    }
}

-(void)updatePlayBtn
{
    if([[FFSingleObject sharedInstance] achiveStringWithWeb:self.entity.file])
    {
        self.playButton.hidden = NO;
        self.photoImageView.hidden = YES;
        [self.playButton setImage:[UIImage imageNamed:@"播放"] forState:UIControlStateNormal];
//        [self.photoImageView sd_setImageWithURL:[NSURL URLWithString:self.entity.pic]];
    }
    else
    {
        self.playButton.hidden = YES;
        self.photoImageView.hidden = YES;
    }
}

- (UIImageView *)photoImageView {
    if(!_photoImageView)
    {
        _photoImageView = [self createImageView];
        [_photoImageView.layer setMasksToBounds:YES];
        _photoImageView.contentMode = UIViewContentModeScaleAspectFill;//等比缩放图片把整个ImageView填充满,所以可能会出现图片部分显示不出来
        _photoImageView.hidden = YES;
        _photoImageView.backgroundColor = [UIColor whiteColor];
        _photoImageView.userInteractionEnabled = YES;
    }
    return _photoImageView;
}

- (UIButton *)playButton {
    
    if (!_playButton)
    {
        _playButton = [[UIButton alloc] init];
        [_playButton setTitle:@"" forState:UIControlStateNormal];
        [_playButton setImage:[UIImage imageNamed:@"播放"] forState:UIControlStateNormal];
        _playButton.backgroundColor = [UIColor clearColor];
        _playButton.userInteractionEnabled = YES;
        _playButton.hidden = YES;
        @weakify(self);
        [[_playButton rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(id x) {
            @strongify(self);
            if(self.isPlay)
            {
                [self hiddenPlayer];
            }
            else
            {
                [self.playButton setImage:[UIImage imageNamed:@"暂停"] forState:UIControlStateNormal];
                self.isPlay = YES;
                self.photoImageView.hidden = NO;
                self.playButton.hidden = NO;
                if([[FFSingleObject sharedInstance] achiveStringWithWeb:self.entity.pic])
                {
                    [self.photoImageView sd_setImageWithURL:[NSURL URLWithString:self.entity.pic]];
                }
                //网络视频路径
                NSString *webVideoPath = self.entity.file;//@"http://api.junqingguanchashi.net/yunpan/bd/c.php?vid=/junqing/1129.mp4";
                NSURL *webVideoUrl = [NSURL URLWithString:webVideoPath];
                AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:webVideoUrl];
                self.currentPlayerItem = playerItem;
                self.player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
                AVPlayerLayer *avLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
                avLayer.videoGravity = AVLayerVideoGravityResizeAspect;
                avLayer.frame = self.photoImageView.bounds;
                [self.photoImageView.layer addSublayer:avLayer];
                //1.注册观察者,监测播放器属性
                //观察Status属性,可以在加载成功之后得到视频的长度
                [self.player.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
                //观察loadedTimeRanges,可以获取缓存进度,实现缓冲进度条
                [self.player.currentItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
            }
        }];
    }
    return _playButton;
}

页面离开处理:

-(void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:NO];
    [self.view endEditing:YES];
    [self.collectionView.refreshView endAnimating];
    [self.chooseSongHeadView hiddenPlayer];
}

点击按钮进行播放和暂停,进入后台停止播放:

    @weakify(self);
    self.imagesScrollView.displayBlock = ^(JCTBannerEntity *entity) {
        @strongify(self);
        self.entity = entity;
        if(!self.isPlay)
        {
            [self updatePlayBtn];
        }
    };
    
    [[[NSNotificationCenter defaultCenter] rac_addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil] subscribeNext:^(id x) {
        @strongify(self);
        [self hiddenPlayer];
    }];
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值