AVFoundation – AVPlayerItem 管理资源对象

ChatGPT 3.5 国内中文镜像站免费使用啦

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> Object-C 基础

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> Object-C 线程

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> OpenGL ES

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> GPUImage

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> AVFoundation

零基础 Object-C 学习路线推荐 : Object-C 学习目录 >> CocoaPods


一.前言

1.AVAsset

Assets 可以来自一个文件或用户的相册,可以理解为多媒体资源,通过 URL 作为一个 asset 对象的标识. 这个 URL 可以是本地文件路径或网络流;


2.AVAssetTrack

AVAsset 包含很多轨道 AVAssetTrack 的结合,如 audio, video, text, closed captions, subtitles…


3.AVComposition / AVMutableComposition

使用 AVMutableComposition 类可以增删 AVAsset 来将单个或者多个 AVAsset 集合到一起,用来合成新视频。除此之外,若想将集合到一起的视听资源以自定义的方式进行播放,需要使用 AVMutableAudioMix 和 AVMutableVideoComposition 类对其中的资源进行协调管理;


4.AVMutableVideoComposition

AVFoundation 类 API 中最核心的类是 AVVideoComposition / AVMutableVideoComposition 。

AVVideoComposition / AVMutableVideoComposition 对两个或多个视频轨道组合在一起的方法给出了一个总体描述。它由一组时间范围和描述组合行为的介绍内容组成。这些信息出现在组合资源内的任意时间点。

AVVideoComposition / AVMutableVideoComposition 管理所有视频轨道,可以决定最终视频的尺寸,裁剪需要在这里进行;


5.AVMutableCompositionTrack

多个 AVAsset 集合到一起合成新视频中轨道信息,有音频轨、视频轨等,里面可以插入各种对应的素材(画中画,水印等);


6.AVMutableVideoCompositionLayerInstruction

AVMutableVideoCompositionLayerInstruction 主要用于对视频轨道中的一个视频处理缩放、模糊、裁剪、旋转等;


7.AVMutableVideoCompositionInstruction

表示一个指令,决定一个 timeRange 内每个轨道的状态,每一个指令包含多个 AVMutableVideoCompositionLayerInstruction ;而 AVVideoComposition 由多个 AVVideoCompositionInstruction 构成;

AVVideoCompositionInstruction 所提供的最关键的一段数据是组合对象时间轴内的时间范围信息。这一时间范围是在某一组合形式出现时的时间范围。要执行的组全特质是通过其 AVMutableVideoCompositionLayerInstruction 集合定义的。


8.AVAssetExportSession

AVAssetExportSession 主要用于导出视频;


二.AVPlayer 简介

首先在 iOS 平台使用播放视频,可用的选项一般有这四个,他们各自的作用和功能如下: 

AVFoundation – AVPlayer 播放视频

由此可以看出,如果我们不做直播功能 AVPlayer 就是一个最优的选择。在创建一个播放器之前我们需要先了解一些播放器相关的类


1.AVPlayer

AVPlayer 控制播放器的播放,暂停,播放速度;

<em>/*创建AVPlayer播放器*/</em>
+ (<strong>instancetype</strong>)playerWithURL:(NSURL *)URL;
+ (<strong>instancetype</strong>)playerWithPlayerItem:(<strong>nullable</strong> AVPlayerItem *)item;
- (<strong>instancetype</strong>)initWithURL:(NSURL *)URL;
- (<strong>instancetype</strong>)initWithPlayerItem:(<strong>nullable</strong> AVPlayerItem *)item;
<em>/*当前播放器播放的时间*/</em>
- (CMTime)currentTime;
<em>/*播放速度
rate = 0.5; // 慢放
rate = 1.0; // 正常播放
rate = 0.0; // 暂停
rate = -0.5; // 倒放
*/</em>
<strong>@property</strong> (<strong>nonatomic</strong>) <strong>float</strong> rate;
<em>/*播放 默认 rate = 1.0*/</em>
- (<strong>void</strong>)play;
<em>/*暂停播放 rate = 0.0*/</em>
- (<strong>void</strong>)pause;
<em>/*创建AVPlayer播放器*/</em>
+ (<strong>instancetype</strong>)playerWithURL:(NSURL *)URL;
+ (<strong>instancetype</strong>)playerWithPlayerItem:(<strong>nullable</strong> AVPlayerItem *)item;
- (<strong>instancetype</strong>)initWithURL:(NSURL *)URL;
- (<strong>instancetype</strong>)initWithPlayerItem:(<strong>nullable</strong> AVPlayerItem *)item;

<em>/*当前播放器播放的时间*/</em>
- (CMTime)currentTime;

<em>/*播放速度
    rate = 0.5;   // 慢放
    rate = 1.0;   // 正常播放
    rate = 0.0;   // 暂停
    rate = -0.5;  // 倒放
 */</em>
<strong>@property</strong> (<strong>nonatomic</strong>) <strong>float</strong> rate;

<em>/*播放 默认 rate = 1.0*/</em>
- (<strong>void</strong>)play;

<em>/*暂停播放 rate = 0.0*/</em>
- (<strong>void</strong>)pause;
/*创建AVPlayer播放器*/ + (instancetype)playerWithURL:(NSURL *)URL; + (instancetype)playerWithPlayerItem:(nullable AVPlayerItem *)item; - (instancetype)initWithURL:(NSURL *)URL; - (instancetype)initWithPlayerItem:(nullable AVPlayerItem *)item; /*当前播放器播放的时间*/ - (CMTime)currentTime; /*播放速度 rate = 0.5; // 慢放 rate = 1.0; // 正常播放 rate = 0.0; // 暂停 rate = -0.5; // 倒放 */ @property (nonatomic) float rate; /*播放 默认 rate = 1.0*/ - (void)play; /*暂停播放 rate = 0.0*/ - (void)pause;

注意更改播放速度要在视频开始播放之后才会生效;


2.AVURLAsset

前面文章有对 AVAsset 介绍,AVURLAsset 是 AVAsset 的一个子类,使用 URL 进行实例化,实例化对象包换 URL 对应视频资源的所有信息;

NSURL *url = <<em>#A URL that identifies an audiovisual asset such as a movie file#>;</em>
AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
NSURL *url = <<em>#A URL that identifies an audiovisual asset such as a movie file#>;</em>
AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:url options:nil];
NSURL *url = <#A URL that identifies an audiovisual asset such as a movie file#>; AVURLAsset *anAsset = [[AVURLAsset alloc] initWithURL:url options:nil];

注意 NSURL 的使用:

[NSURL URLWithString:@"网络路径"]
[NSURL fileURLWithPath:@"本地路径"]
如果读取的是本地文件,那么请用第二个方法,第一个会出错,读取不到URL.
[NSURL URLWithString:@"网络路径"]
[NSURL fileURLWithPath:@"本地路径"]
如果读取的是本地文件,那么请用第二个方法,第一个会出错,读取不到URL.
[NSURL URLWithString:@"网络路径"] [NSURL fileURLWithPath:@"本地路径"] 如果读取的是本地文件,那么请用第二个方法,第一个会出错,读取不到URL.

3.AVPlayerItem

AVPlayerItem 管理资源对象,提供播放数据源;


4.AVPlayerLayer

AVPlayerLayer 负责显示视频,如果没有添加该类,只有声音没有画面;


三.获取 AVPlayerItem 播放状态

AVPlayerItem 作为资源管理对象,它控制着视频从创建到销毁的诸多状态。

<em>//播放状态 status</em>
<strong>typedef</strong> NS_ENUM(NSInteger,AVPlayerItemStatus) {
AVPlayerItemStatusUnknown, <em>//未知</em>
AVPlayerItemStatusReadyToPlay, <em>//准备播放</em>
AVPlayerItemStatusFailed <em>//播放失败</em>
};
<em>//播放状态 status</em>

<strong>typedef</strong> NS_ENUM(NSInteger,AVPlayerItemStatus) {

    AVPlayerItemStatusUnknown,      <em>//未知</em>
    AVPlayerItemStatusReadyToPlay,  <em>//准备播放</em>
    AVPlayerItemStatusFailed        <em>//播放失败</em>

};
//播放状态 status typedef NS_ENUM(NSInteger,AVPlayerItemStatus) { AVPlayerItemStatusUnknown, //未知 AVPlayerItemStatusReadyToPlay, //准备播放 AVPlayerItemStatusFailed //播放失败 };

在上一篇文章 《AVPlayer播放视频》最后提示:

AVPlayer 创建后,播放并不是可以直接使用,还要对它的状态进行检查,只有 AVPlayerItem.status 的值为 AVPlayerStatusReadyToPlay 时,才能进行播放,所以这里需要使用 KVO 模式对该状态进行监控,以决定何时可以进行播放;


示例代码如下:

/******************************************************************************************/
//@Author:猿说编程
//@Blog(个人博客地址): www.codersrc.com
//@File:AVFoundation - AVPlayerItem 管理资源对象
//@Time:2021/08/04 07:30
//@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
/******************************************************************************************/
<strong>#import "ViewController.h"</strong>
<strong>#import <AVFoundation/AVFoundation.h></strong>
<strong>@interface</strong> <strong>ViewController</strong> ()
{
AVPlayerItem* _item ; <em>//用于加载媒体</em>
AVPlayer* _player; <em>//控制播放器的播放,暂停,播放速度</em>
AVPlayerLayer* _playerLayer; <em>//用于显示画面</em>
}
<strong>@end</strong>
<strong>@implementation</strong> <strong>ViewController</strong>
- (<strong>void</strong>)viewDidLoad
{
[<strong>super</strong> viewDidLoad];
<em>// self.view.backgroundColor = [UIColor redColor];</em>
<em>//创建一个资源实例</em>
NSURL* url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"123.mp4" ofType:nil]];
AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil];
<em>//AVPlayerItem关联播放资源</em>
_item = [[AVPlayerItem alloc] initWithAsset:asset];
<em>//添加观察者,对该状态进行监控,以决定何时可以进行播放</em>
[_item addObserver:<strong>self</strong> forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
<em>//创建AVPlayer</em>
_player = [AVPlayer playerWithPlayerItem:_item];
<em>//创建AVPlayerLayer用来显示资源内容</em>
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
<em>//设置frame</em>
_playerLayer.frame = <strong>self</strong>.view.frame;
<em>//添加到当前的view,否则无法显示</em>
[<strong>self</strong>.view.layer addSublayer:_playerLayer];
}
- (<strong>void</strong>)observeValueForKeyPath:(NSString *)keyPath ofObject:(<strong>id</strong>)object change:(NSDictionary<NSKeyValueChangeKey,<strong>id</strong>> *)change context:(<strong>void</strong> *)context {
<strong>if</strong> ([object isKindOfClass:[AVPlayerItem <strong>class</strong>]]) {
<strong>if</strong>([keyPath isEqualToString:@"status"])
{
<strong>switch</strong>(_item.status)
{
<strong>case</strong> AVPlayerItemStatusReadyToPlay:
[_player play];
NSLog(@"AVPlayerItemStatusReadyToPlay");
<strong>break</strong>;
<strong>case</strong> AVPlayerItemStatusUnknown:
NSLog(@"AVPlayerItemStatusUnknown");
<strong>break</strong>;
<strong>case</strong> AVPlayerItemStatusFailed:
NSLog(@"AVPlayerItemStatusFailed");
<strong>break</strong>;
<strong>default</strong>:<strong>break</strong>;
}
}
}
}
- (<strong>void</strong>)dealloc
{
<em>//删除观察者</em>
[<strong>self</strong> removeObserver:<strong>self</strong> forKeyPath:@"status"];
}
<strong>@end</strong>
/******************************************************************************************/
//@Author:猿说编程
//@Blog(个人博客地址): www.codersrc.com
//@File:AVFoundation - AVPlayerItem 管理资源对象
//@Time:2021/08/04 07:30
//@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
/******************************************************************************************/

<strong>#import "ViewController.h"</strong>
<strong>#import <AVFoundation/AVFoundation.h></strong>

<strong>@interface</strong> <strong>ViewController</strong> ()
{
    AVPlayerItem* _item ;         <em>//用于加载媒体</em>
    AVPlayer* _player;            <em>//控制播放器的播放,暂停,播放速度</em>
    AVPlayerLayer* _playerLayer;  <em>//用于显示画面</em>
}


<strong>@end</strong>

<strong>@implementation</strong> <strong>ViewController</strong>

- (<strong>void</strong>)viewDidLoad
{
    [<strong>super</strong> viewDidLoad];
<em>//    self.view.backgroundColor = [UIColor redColor];</em>
    
    <em>//创建一个资源实例</em>
    NSURL* url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"123.mp4" ofType:nil]];
    AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil];
    
    <em>//AVPlayerItem关联播放资源</em>
    _item = [[AVPlayerItem alloc] initWithAsset:asset];
    
    <em>//添加观察者,对该状态进行监控,以决定何时可以进行播放</em>
    [_item addObserver:<strong>self</strong> forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    
    <em>//创建AVPlayer</em>
    _player = [AVPlayer playerWithPlayerItem:_item];
   
    
    <em>//创建AVPlayerLayer用来显示资源内容</em>
    _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
    <em>//设置frame</em>
    _playerLayer.frame = <strong>self</strong>.view.frame;
    <em>//添加到当前的view,否则无法显示</em>
    [<strong>self</strong>.view.layer addSublayer:_playerLayer];
    
}

- (<strong>void</strong>)observeValueForKeyPath:(NSString *)keyPath ofObject:(<strong>id</strong>)object change:(NSDictionary<NSKeyValueChangeKey,<strong>id</strong>> *)change context:(<strong>void</strong> *)context {
    <strong>if</strong> ([object isKindOfClass:[AVPlayerItem <strong>class</strong>]]) {
        <strong>if</strong>([keyPath isEqualToString:@"status"])
        {
            <strong>switch</strong>(_item.status)
            {
                <strong>case</strong> AVPlayerItemStatusReadyToPlay:
                    [_player play];
                    NSLog(@"AVPlayerItemStatusReadyToPlay");
                    <strong>break</strong>;
                <strong>case</strong> AVPlayerItemStatusUnknown:
                    NSLog(@"AVPlayerItemStatusUnknown");
                    <strong>break</strong>;
                <strong>case</strong> AVPlayerItemStatusFailed:
                    NSLog(@"AVPlayerItemStatusFailed");
                    <strong>break</strong>;

                <strong>default</strong>:<strong>break</strong>;
            }
        }
    }
}
- (<strong>void</strong>)dealloc
{
    <em>//删除观察者</em>
    [<strong>self</strong> removeObserver:<strong>self</strong> forKeyPath:@"status"];
}

<strong>@end</strong>
/******************************************************************************************/ //@Author:猿说编程 //@Blog(个人博客地址): www.codersrc.com //@File:AVFoundation - AVPlayerItem 管理资源对象 //@Time:2021/08/04 07:30 //@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累! /******************************************************************************************/ #import "ViewController.h" #import <AVFoundation/AVFoundation.h> @interface ViewController () { AVPlayerItem* _item ; //用于加载媒体 AVPlayer* _player; //控制播放器的播放,暂停,播放速度 AVPlayerLayer* _playerLayer; //用于显示画面 } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // self.view.backgroundColor = [UIColor redColor]; //创建一个资源实例 NSURL* url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"123.mp4" ofType:nil]]; AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil]; //AVPlayerItem关联播放资源 _item = [[AVPlayerItem alloc] initWithAsset:asset]; //添加观察者,对该状态进行监控,以决定何时可以进行播放 [_item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; //创建AVPlayer _player = [AVPlayer playerWithPlayerItem:_item]; //创建AVPlayerLayer用来显示资源内容 _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player]; //设置frame _playerLayer.frame = self.view.frame; //添加到当前的view,否则无法显示 [self.view.layer addSublayer:_playerLayer]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { if ([object isKindOfClass:[AVPlayerItem class]]) { if([keyPath isEqualToString:@"status"]) { switch(_item.status) { case AVPlayerItemStatusReadyToPlay: [_player play]; NSLog(@"AVPlayerItemStatusReadyToPlay"); break; case AVPlayerItemStatusUnknown: NSLog(@"AVPlayerItemStatusUnknown"); break; case AVPlayerItemStatusFailed: NSLog(@"AVPlayerItemStatusFailed"); break; default:break; } } } } - (void)dealloc { //删除观察者 [self removeObserver:self forKeyPath:@"status"]; } @end

四.时间监听


1.定期监听

<em>//@interface AVPlayer (AVPlayerTimeObservation)</em>
/*
* 函数描述:以一定的时间间隔获得通知,比如需要随着时间的变化移动播放头位置或更新时间显示;
* 函数参数:
*
* interval:指定通知周期间隔的CMTime值(例如:间隔1秒通知播放器滑块刷新);
* queue:默认为主队列。不可以使用并行调度队列,API没有处理并行队列的方法;
* block:一个在指定的时间间隔中就会在队列上调用的回调块。这个块传递一个CMTime值用于指示播放器的当前时间;
*
<strong>*/
- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;
</strong>
<em>//@interface AVPlayer (AVPlayerTimeObservation)</em>

/*
* 函数描述:以一定的时间间隔获得通知,比如需要随着时间的变化移动播放头位置或更新时间显示;

* 函数参数:
*
*   interval:指定通知周期间隔的CMTime值(例如:间隔1秒通知播放器滑块刷新);
*   queue:默认为主队列。不可以使用并行调度队列,API没有处理并行队列的方法;
*   block:一个在指定的时间间隔中就会在队列上调用的回调块。这个块传递一个CMTime值用于指示播放器的当前时间;
*
<strong>*/
- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;

</strong>
//@interface AVPlayer (AVPlayerTimeObservation) /* * 函数描述:以一定的时间间隔获得通知,比如需要随着时间的变化移动播放头位置或更新时间显示; * 函数参数: * * interval:指定通知周期间隔的CMTime值(例如:间隔1秒通知播放器滑块刷新); * queue:默认为主队列。不可以使用并行调度队列,API没有处理并行队列的方法; * block:一个在指定的时间间隔中就会在队列上调用的回调块。这个块传递一个CMTime值用于指示播放器的当前时间; * */ - (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;

2.边界时间监听

<em>//@interface AVPlayer (AVPlayerTimeObservation)</em>
/*
* 函数描述:监听时间,可以得到播放器时间轴中多个边界点的遍历结果,比如可以定义 25%、50% 边界的标记,当播放器的播放到 25% 或者 50%会触发 block 回调;
* 函数参数:
*
* times:CMTime 值组成的一个 NSArray 数组定义了需要通知的边界点;
* queue:与定期监听类似,为方法提供一个用来发送通知的顺序调度队列。指定NULL等同于明确设置主队列;
* block:每当正常播放中跨域一个边界点时就会在队列中回调方法块,不提供遍历的CMTime值,需要为此执行一些额外计算进行确定;
*
<strong>*/
</strong>- (id)addBoundaryTimeObserverForTimes:(NSArray<NSValue <strong>*> *</strong>)times queue:(nullable dispatch<em>_queue_</em>t)queue usingBlock:(void (^)(void))block;
<em>//@interface AVPlayer (AVPlayerTimeObservation)</em>

/*
* 函数描述:监听时间,可以得到播放器时间轴中多个边界点的遍历结果,比如可以定义 25%、50% 边界的标记,当播放器的播放到 25% 或者 50%会触发 block 回调;

* 函数参数:
*
*   times:CMTime 值组成的一个 NSArray 数组定义了需要通知的边界点;
*   queue:与定期监听类似,为方法提供一个用来发送通知的顺序调度队列。指定NULL等同于明确设置主队列;
*   block:每当正常播放中跨域一个边界点时就会在队列中回调方法块,不提供遍历的CMTime值,需要为此执行一些额外计算进行确定;
*
<strong>*/

</strong>- (id)addBoundaryTimeObserverForTimes:(NSArray<NSValue <strong>*> *</strong>)times queue:(nullable dispatch<em>_queue_</em>t)queue usingBlock:(void (^)(void))block;
//@interface AVPlayer (AVPlayerTimeObservation) /* * 函数描述:监听时间,可以得到播放器时间轴中多个边界点的遍历结果,比如可以定义 25%、50% 边界的标记,当播放器的播放到 25% 或者 50%会触发 block 回调; * 函数参数: * * times:CMTime 值组成的一个 NSArray 数组定义了需要通知的边界点; * queue:与定期监听类似,为方法提供一个用来发送通知的顺序调度队列。指定NULL等同于明确设置主队列; * block:每当正常播放中跨域一个边界点时就会在队列中回调方法块,不提供遍历的CMTime值,需要为此执行一些额外计算进行确定; * */ - (id)addBoundaryTimeObserverForTimes:(NSArray<NSValue *> *)times queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(void))block;

3.播放结束通知

播放完成时,AVPlayerItem 会发送 AVPlayerItemDidPlayToEndTimeNotification 通知 。注册成为监听器,即获得播放器结束通知。


4.完整代码

/******************************************************************************************/
//@Author:猿说编程
//@Blog(个人博客地址): www.codersrc.com
//@File:AVFoundation - AVPlayerItem 管理资源对象
//@Time:2021/08/04 07:30
//@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
/******************************************************************************************/
<strong>#import "ViewController.h"</strong>
<strong>#import <AVFoundation/AVFoundation.h></strong>
<strong>@interface</strong> <strong>ViewController</strong> ()
{
AVPlayerItem* _item ; <em>//用于加载媒体</em>
AVPlayer* _player; <em>//控制播放器的播放,暂停,播放速度</em>
AVPlayerLayer* _playerLayer; <em>//用于显示画面</em>
<strong>float</strong> _duration; <em>//媒体的时间</em>
}
<strong>@end</strong>
<strong>@implementation</strong> <strong>ViewController</strong>
<strong>#pragma mark - create UISlider</strong>
- (UISlider*)createSlider {
<em>/// 创建Slider 设置Frame</em>
UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, 100, 247, 50)];
<em>/// 属性配置</em>
<em>// minimumValue : 当值可以改变时,滑块可以滑动到最小位置的值,默认为0.0</em>
slider.minimumValue = 0.0;
<em>// maximumValue : 当值可以改变时,滑块可以滑动到最大位置的值,默认为1.0</em>
slider.maximumValue = 1.0;
<em>// 当前值,这个值是介于滑块的最大值和最小值之间的,如果没有设置边界值,默认为0-1;</em>
slider.value = 0;
<em>// continuous : 如果设置YES,在拖动滑块的任何时候,滑块的值都会改变。默认设置为YES</em>
[slider setContinuous:YES];
<em>// minimumTrackTintColor : 小于滑块当前值滑块条的颜色,默认为蓝色</em>
slider.minimumTrackTintColor = [UIColor redColor];
<em>// maximumTrackTintColor: 大于滑块当前值滑块条的颜色,默认为白色</em>
slider.maximumTrackTintColor = [UIColor blueColor];
<em>// thumbTintColor : 当前滑块的颜色,默认为白色</em>
slider.thumbTintColor = [UIColor yellowColor];
<em>// minimumTrackTintColor : 小于滑块当前值滑块条的颜色,默认为蓝色</em>
slider.minimumTrackTintColor = [UIColor redColor];
<em>// maximumTrackTintColor: 大于滑块当前值滑块条的颜色,默认为白色</em>
slider.maximumTrackTintColor = [UIColor blueColor];
<em>// thumbTintColor : 当前滑块的颜色,默认为白色</em>
slider.thumbTintColor = [UIColor yellowColor];
<strong>return</strong> slider;
}
<strong>#pragma mark - seek</strong>
- (<strong>void</strong>)_sliderValueDidChanged:(<strong>id</strong>)sender {
UISlider *slider = (UISlider*)sender;
NSLog(@"slider:%f _player.currentTime:%f",slider.value,CMTimeGetSeconds(_player.currentTime));
<em>//seek</em>
[_player seekToTime:CMTimeMake(slider.value*_duration*60, 60) toleranceBefore:CMTimeMake(1, 1000) toleranceAfter:CMTimeMake(1, 1000)];
<em>//play</em>
[_player play];
;
}
- (<strong>void</strong>)viewDidLoad
{
[<strong>super</strong> viewDidLoad];
<em>//创建滑块</em>
UISlider *slider = [<strong>self</strong> createSlider];
<em>// 事件监听</em>
[slider addTarget:<strong>self</strong> action:<strong>@selector</strong>(_sliderValueDidChanged:) forControlEvents:UIControlEventValueChanged];
[<strong>self</strong>.view addSubview:slider];
<em>//创建label用于显示时间</em>
UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[<strong>self</strong>.view addSubview:label];
<em>//创建一个资源实例</em>
NSURL* url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"123.mp4" ofType:nil]];
AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil];
<em>//获取总时间</em>
_duration = CMTimeGetSeconds(asset.duration);
<em>//AVPlayerItem关联播放资源</em>
_item = [[AVPlayerItem alloc] initWithAsset:asset];
<em>//添加观察者,对该状态进行监控,以决定何时可以进行播放</em>
[_item addObserver:<strong>self</strong> forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
<em>//监听播放结束通知</em>
[[NSNotificationCenter defaultCenter] addObserver:<strong>self</strong>
selector:<strong>@selector</strong>(playFinishNotification:) name:AVPlayerItemDidPlayToEndTimeNotification object:_item];
<em>//创建AVPlayer</em>
_player = [AVPlayer playerWithPlayerItem:_item];
<em>//每隔1秒在主队列中触发block回调,刷新滑块,显示时间</em>
[_player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
<strong>float</strong> currentTime = CMTimeGetSeconds(time); <em>//当前时间,以秒为单位</em>
slider.value = currentTime/_duration; <em>//当前时间百分比</em>
label.text = [NSString stringWithFormat:@"%.0f:%.0f",currentTime,_duration];<em>//显示当前时间,秒为单位</em>
}];
<em>//设置边界时间</em>
NSValue* value1 = [NSValue valueWithCMTime:CMTimeMake(10, 1)]; <em>//第10秒</em>
NSValue* value2 = [NSValue valueWithCMTime:CMTimeMake(20, 1)]; <em>//第20秒</em>
NSArray* times = [NSArray arrayWithObjects:value1, value2, nil];
<em>//当播放器播放到边界时间,会自动触发black回调</em>
[_player addBoundaryTimeObserverForTimes:times queue:dispatch_get_main_queue() usingBlock:^{
NSLog(@"边界时间:%@ 播放器当前时间:%f",times,CMTimeGetSeconds(_player.currentTime) );
}];
<em>//创建AVPlayerLayer用来显示资源内容</em>
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
<em>//设置frame</em>
_playerLayer.frame = <strong>self</strong>.view.frame;
<em>//添加到当前的view,否则无法显示</em>
[<strong>self</strong>.view.layer addSublayer:_playerLayer];
}
- (<strong>void</strong>)playFinishNotification:(NSNotification *)notification {
<em>//播放结束,并seek到文件开始位置</em>
[_player seekToTime:kCMTimeZero completionHandler:^(BOOL finished) {
NSLog(@"播放结束啦....");
}];
}
- (<strong>void</strong>)observeValueForKeyPath:(NSString *)keyPath ofObject:(<strong>id</strong>)object change:(NSDictionary<NSKeyValueChangeKey,<strong>id</strong>> *)change context:(<strong>void</strong> *)context {
<strong>if</strong> ([object isKindOfClass:[AVPlayerItem <strong>class</strong>]]) {
<strong>if</strong>([keyPath isEqualToString:@"status"])
{
<strong>switch</strong>(_item.status)
{
<strong>case</strong> AVPlayerItemStatusReadyToPlay:
[_player play];
NSLog(@"AVPlayerItemStatusReadyToPlay");
<strong>break</strong>;
<strong>case</strong> AVPlayerItemStatusUnknown:
NSLog(@"AVPlayerItemStatusUnknown");
<strong>break</strong>;
<strong>case</strong> AVPlayerItemStatusFailed:
NSLog(@"AVPlayerItemStatusFailed");
<strong>break</strong>;
<strong>default</strong>:<strong>break</strong>;
}
}
}
}
- (<strong>void</strong>)dealloc
{
<em>//删除观察者</em>
[<strong>self</strong> removeObserver:<strong>self</strong> forKeyPath:@"status"];
<em>//删除监听</em>
[[NSNotificationCenter defaultCenter] removeObserver:<strong>self</strong>];
}
<strong>@end</strong>
<em>/*
2021-07-31 11:29:41.023583+0800 LearnAVFoundation[2411:143670] AVPlayerItemStatusReadyToPlay
2021-07-31 11:29:51.108482+0800 LearnAVFoundation[2411:143670] 边界时间:(
"CMTime: {10/1 = 10.000}",
"CMTime: {20/1 = 20.000}"
) 播放器当前时间:10.001048
2021-07-31 11:30:01.107947+0800 LearnAVFoundation[2411:143670] 边界时间:(
"CMTime: {10/1 = 10.000}",
"CMTime: {20/1 = 20.000}"
) 播放器当前时间:20.000597
*/</em>
/******************************************************************************************/
//@Author:猿说编程
//@Blog(个人博客地址): www.codersrc.com
//@File:AVFoundation - AVPlayerItem 管理资源对象
//@Time:2021/08/04 07:30
//@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!
/******************************************************************************************/

<strong>#import "ViewController.h"</strong>
<strong>#import <AVFoundation/AVFoundation.h></strong>



<strong>@interface</strong> <strong>ViewController</strong> ()
{
    AVPlayerItem* _item ;         <em>//用于加载媒体</em>
    AVPlayer* _player;            <em>//控制播放器的播放,暂停,播放速度</em>
    AVPlayerLayer* _playerLayer;  <em>//用于显示画面</em>
    <strong>float</strong> _duration;              <em>//媒体的时间</em>
}


<strong>@end</strong>

<strong>@implementation</strong> <strong>ViewController</strong>



<strong>#pragma mark - create UISlider</strong>
- (UISlider*)createSlider {
    
    <em>/// 创建Slider 设置Frame</em>
    UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, 100, 247, 50)];
    
    <em>/// 属性配置</em>
    <em>// minimumValue  : 当值可以改变时,滑块可以滑动到最小位置的值,默认为0.0</em>
    slider.minimumValue = 0.0;
    <em>// maximumValue : 当值可以改变时,滑块可以滑动到最大位置的值,默认为1.0</em>
    slider.maximumValue = 1.0;
    <em>// 当前值,这个值是介于滑块的最大值和最小值之间的,如果没有设置边界值,默认为0-1;</em>
    slider.value = 0;
    
    <em>// continuous : 如果设置YES,在拖动滑块的任何时候,滑块的值都会改变。默认设置为YES</em>
    [slider setContinuous:YES];
    
    <em>// minimumTrackTintColor : 小于滑块当前值滑块条的颜色,默认为蓝色</em>
    slider.minimumTrackTintColor = [UIColor redColor];
    <em>// maximumTrackTintColor: 大于滑块当前值滑块条的颜色,默认为白色</em>
    slider.maximumTrackTintColor = [UIColor blueColor];
    <em>// thumbTintColor : 当前滑块的颜色,默认为白色</em>
    slider.thumbTintColor = [UIColor yellowColor];
    
    <em>// minimumTrackTintColor : 小于滑块当前值滑块条的颜色,默认为蓝色</em>
    slider.minimumTrackTintColor = [UIColor redColor];
    <em>// maximumTrackTintColor: 大于滑块当前值滑块条的颜色,默认为白色</em>
    slider.maximumTrackTintColor = [UIColor blueColor];
    <em>// thumbTintColor : 当前滑块的颜色,默认为白色</em>
    slider.thumbTintColor = [UIColor yellowColor];
    
    <strong>return</strong> slider;
}
<strong>#pragma mark - seek</strong>
- (<strong>void</strong>)_sliderValueDidChanged:(<strong>id</strong>)sender {
    
    UISlider *slider = (UISlider*)sender;
    NSLog(@"slider:%f _player.currentTime:%f",slider.value,CMTimeGetSeconds(_player.currentTime));
    <em>//seek</em>
    [_player seekToTime:CMTimeMake(slider.value*_duration*60, 60) toleranceBefore:CMTimeMake(1, 1000) toleranceAfter:CMTimeMake(1, 1000)];
    <em>//play</em>
    [_player play];
    ;
}

- (<strong>void</strong>)viewDidLoad
{
    [<strong>super</strong> viewDidLoad];
    
    <em>//创建滑块</em>
    UISlider *slider = [<strong>self</strong> createSlider];
    <em>// 事件监听</em>
    [slider addTarget:<strong>self</strong> action:<strong>@selector</strong>(_sliderValueDidChanged:) forControlEvents:UIControlEventValueChanged];
    [<strong>self</strong>.view addSubview:slider];
    
    <em>//创建label用于显示时间</em>
    UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    [<strong>self</strong>.view addSubview:label];
        
    <em>//创建一个资源实例</em>
    NSURL* url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"123.mp4" ofType:nil]];
    AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil];
    
    <em>//获取总时间</em>
    _duration = CMTimeGetSeconds(asset.duration);
    
    <em>//AVPlayerItem关联播放资源</em>
    _item = [[AVPlayerItem alloc] initWithAsset:asset];
    

    <em>//添加观察者,对该状态进行监控,以决定何时可以进行播放</em>
    [_item addObserver:<strong>self</strong> forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    <em>//监听播放结束通知</em>
    [[NSNotificationCenter defaultCenter] addObserver:<strong>self</strong>
                                                 selector:<strong>@selector</strong>(playFinishNotification:) name:AVPlayerItemDidPlayToEndTimeNotification object:_item];
    
    
    
    <em>//创建AVPlayer</em>
    _player = [AVPlayer playerWithPlayerItem:_item];
   
    <em>//每隔1秒在主队列中触发block回调,刷新滑块,显示时间</em>
    [_player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
        <strong>float</strong> currentTime = CMTimeGetSeconds(time); <em>//当前时间,以秒为单位</em>
        slider.value = currentTime/_duration;       <em>//当前时间百分比</em>
        label.text = [NSString stringWithFormat:@"%.0f:%.0f",currentTime,_duration];<em>//显示当前时间,秒为单位</em>
    }];
    
    
    <em>//设置边界时间</em>
    NSValue* value1 = [NSValue valueWithCMTime:CMTimeMake(10, 1)]; <em>//第10秒</em>
    NSValue* value2 = [NSValue valueWithCMTime:CMTimeMake(20, 1)]; <em>//第20秒</em>
    NSArray* times = [NSArray arrayWithObjects:value1, value2, nil];
    <em>//当播放器播放到边界时间,会自动触发black回调</em>
    [_player addBoundaryTimeObserverForTimes:times queue:dispatch_get_main_queue() usingBlock:^{
        
        NSLog(@"边界时间:%@ 播放器当前时间:%f",times,CMTimeGetSeconds(_player.currentTime) );
    }];
    
    
    <em>//创建AVPlayerLayer用来显示资源内容</em>
    _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
    
    
    
    
    <em>//设置frame</em>
    _playerLayer.frame = <strong>self</strong>.view.frame;
    <em>//添加到当前的view,否则无法显示</em>
    [<strong>self</strong>.view.layer addSublayer:_playerLayer];
    
}

- (<strong>void</strong>)playFinishNotification:(NSNotification *)notification {
    
    <em>//播放结束,并seek到文件开始位置</em>
    [_player seekToTime:kCMTimeZero completionHandler:^(BOOL finished) {
        NSLog(@"播放结束啦....");
    }];
}


- (<strong>void</strong>)observeValueForKeyPath:(NSString *)keyPath ofObject:(<strong>id</strong>)object change:(NSDictionary<NSKeyValueChangeKey,<strong>id</strong>> *)change context:(<strong>void</strong> *)context {
    <strong>if</strong> ([object isKindOfClass:[AVPlayerItem <strong>class</strong>]]) {
        <strong>if</strong>([keyPath isEqualToString:@"status"])
        {
            <strong>switch</strong>(_item.status)
            {
                <strong>case</strong> AVPlayerItemStatusReadyToPlay:
                    [_player play];
                    NSLog(@"AVPlayerItemStatusReadyToPlay");
                    <strong>break</strong>;
                <strong>case</strong> AVPlayerItemStatusUnknown:
                    NSLog(@"AVPlayerItemStatusUnknown");
                    <strong>break</strong>;
                <strong>case</strong> AVPlayerItemStatusFailed:
                    NSLog(@"AVPlayerItemStatusFailed");
                    <strong>break</strong>;

                <strong>default</strong>:<strong>break</strong>;
            }
        }
    }
}

- (<strong>void</strong>)dealloc
{
    <em>//删除观察者</em>
    [<strong>self</strong> removeObserver:<strong>self</strong> forKeyPath:@"status"];
    <em>//删除监听</em>
    [[NSNotificationCenter defaultCenter] removeObserver:<strong>self</strong>];
}

<strong>@end</strong>



<em>/*

2021-07-31 11:29:41.023583+0800 LearnAVFoundation[2411:143670] AVPlayerItemStatusReadyToPlay
2021-07-31 11:29:51.108482+0800 LearnAVFoundation[2411:143670] 边界时间:(
    "CMTime: {10/1 = 10.000}",
    "CMTime: {20/1 = 20.000}"
) 播放器当前时间:10.001048
2021-07-31 11:30:01.107947+0800 LearnAVFoundation[2411:143670] 边界时间:(
    "CMTime: {10/1 = 10.000}",
    "CMTime: {20/1 = 20.000}"
) 播放器当前时间:20.000597

*/</em>
/******************************************************************************************/ //@Author:猿说编程 //@Blog(个人博客地址): www.codersrc.com //@File:AVFoundation - AVPlayerItem 管理资源对象 //@Time:2021/08/04 07:30 //@Motto:不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累! /******************************************************************************************/ #import "ViewController.h" #import <AVFoundation/AVFoundation.h> @interface ViewController () { AVPlayerItem* _item ; //用于加载媒体 AVPlayer* _player; //控制播放器的播放,暂停,播放速度 AVPlayerLayer* _playerLayer; //用于显示画面 float _duration; //媒体的时间 } @end @implementation ViewController #pragma mark - create UISlider - (UISlider*)createSlider { /// 创建Slider 设置Frame UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, 100, 247, 50)]; /// 属性配置 // minimumValue : 当值可以改变时,滑块可以滑动到最小位置的值,默认为0.0 slider.minimumValue = 0.0; // maximumValue : 当值可以改变时,滑块可以滑动到最大位置的值,默认为1.0 slider.maximumValue = 1.0; // 当前值,这个值是介于滑块的最大值和最小值之间的,如果没有设置边界值,默认为0-1; slider.value = 0; // continuous : 如果设置YES,在拖动滑块的任何时候,滑块的值都会改变。默认设置为YES [slider setContinuous:YES]; // minimumTrackTintColor : 小于滑块当前值滑块条的颜色,默认为蓝色 slider.minimumTrackTintColor = [UIColor redColor]; // maximumTrackTintColor: 大于滑块当前值滑块条的颜色,默认为白色 slider.maximumTrackTintColor = [UIColor blueColor]; // thumbTintColor : 当前滑块的颜色,默认为白色 slider.thumbTintColor = [UIColor yellowColor]; // minimumTrackTintColor : 小于滑块当前值滑块条的颜色,默认为蓝色 slider.minimumTrackTintColor = [UIColor redColor]; // maximumTrackTintColor: 大于滑块当前值滑块条的颜色,默认为白色 slider.maximumTrackTintColor = [UIColor blueColor]; // thumbTintColor : 当前滑块的颜色,默认为白色 slider.thumbTintColor = [UIColor yellowColor]; return slider; } #pragma mark - seek - (void)_sliderValueDidChanged:(id)sender { UISlider *slider = (UISlider*)sender; NSLog(@"slider:%f _player.currentTime:%f",slider.value,CMTimeGetSeconds(_player.currentTime)); //seek [_player seekToTime:CMTimeMake(slider.value*_duration*60, 60) toleranceBefore:CMTimeMake(1, 1000) toleranceAfter:CMTimeMake(1, 1000)]; //play [_player play]; ; } - (void)viewDidLoad { [super viewDidLoad]; //创建滑块 UISlider *slider = [self createSlider]; // 事件监听 [slider addTarget:self action:@selector(_sliderValueDidChanged:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:slider]; //创建label用于显示时间 UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; [self.view addSubview:label]; //创建一个资源实例 NSURL* url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"123.mp4" ofType:nil]]; AVURLAsset* asset = [[AVURLAsset alloc] initWithURL:url options:nil]; //获取总时间 _duration = CMTimeGetSeconds(asset.duration); //AVPlayerItem关联播放资源 _item = [[AVPlayerItem alloc] initWithAsset:asset]; //添加观察者,对该状态进行监控,以决定何时可以进行播放 [_item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; //监听播放结束通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playFinishNotification:) name:AVPlayerItemDidPlayToEndTimeNotification object:_item]; //创建AVPlayer _player = [AVPlayer playerWithPlayerItem:_item]; //每隔1秒在主队列中触发block回调,刷新滑块,显示时间 [_player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) { float currentTime = CMTimeGetSeconds(time); //当前时间,以秒为单位 slider.value = currentTime/_duration; //当前时间百分比 label.text = [NSString stringWithFormat:@"%.0f:%.0f",currentTime,_duration];//显示当前时间,秒为单位 }]; //设置边界时间 NSValue* value1 = [NSValue valueWithCMTime:CMTimeMake(10, 1)]; //第10秒 NSValue* value2 = [NSValue valueWithCMTime:CMTimeMake(20, 1)]; //第20秒 NSArray* times = [NSArray arrayWithObjects:value1, value2, nil]; //当播放器播放到边界时间,会自动触发black回调 [_player addBoundaryTimeObserverForTimes:times queue:dispatch_get_main_queue() usingBlock:^{ NSLog(@"边界时间:%@ 播放器当前时间:%f",times,CMTimeGetSeconds(_player.currentTime) ); }]; //创建AVPlayerLayer用来显示资源内容 _playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player]; //设置frame _playerLayer.frame = self.view.frame; //添加到当前的view,否则无法显示 [self.view.layer addSublayer:_playerLayer]; } - (void)playFinishNotification:(NSNotification *)notification { //播放结束,并seek到文件开始位置 [_player seekToTime:kCMTimeZero completionHandler:^(BOOL finished) { NSLog(@"播放结束啦...."); }]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context { if ([object isKindOfClass:[AVPlayerItem class]]) { if([keyPath isEqualToString:@"status"]) { switch(_item.status) { case AVPlayerItemStatusReadyToPlay: [_player play]; NSLog(@"AVPlayerItemStatusReadyToPlay"); break; case AVPlayerItemStatusUnknown: NSLog(@"AVPlayerItemStatusUnknown"); break; case AVPlayerItemStatusFailed: NSLog(@"AVPlayerItemStatusFailed"); break; default:break; } } } } - (void)dealloc { //删除观察者 [self removeObserver:self forKeyPath:@"status"]; //删除监听 [[NSNotificationCenter defaultCenter] removeObserver:self]; } @end /* 2021-07-31 11:29:41.023583+0800 LearnAVFoundation[2411:143670] AVPlayerItemStatusReadyToPlay 2021-07-31 11:29:51.108482+0800 LearnAVFoundation[2411:143670] 边界时间:( "CMTime: {10/1 = 10.000}", "CMTime: {20/1 = 20.000}" ) 播放器当前时间:10.001048 2021-07-31 11:30:01.107947+0800 LearnAVFoundation[2411:143670] 边界时间:( "CMTime: {10/1 = 10.000}", "CMTime: {20/1 = 20.000}" ) 播放器当前时间:20.000597 */


五.播放相关通知

播放相关通知
1、声音类
<em>//声音被打断的通知(电话打来)</em>
AVAudioSessionInterruptionNotification
<em>//耳机插入和拔出的通知</em>
AVAudioSessionRouteChangeNotification
2、播放类
<em>//播放完成</em>
AVPlayerItemDidPlayToEndTimeNotification
<em>//播放失败</em>
AVPlayerItemFailedToPlayToEndTimeNotification
<em>//异常中断</em>
AVPlayerItemPlaybackStalledNotification
3、系统状态
<em>//进入后台</em>
UIApplicationWillResignActiveNotification
<em>//返回前台</em>
UIApplicationDidBecomeActiveNotification
播放相关通知

1、声音类

<em>//声音被打断的通知(电话打来)</em>
AVAudioSessionInterruptionNotification

<em>//耳机插入和拔出的通知</em>
AVAudioSessionRouteChangeNotification



2、播放类

<em>//播放完成</em>
AVPlayerItemDidPlayToEndTimeNotification

<em>//播放失败</em>
AVPlayerItemFailedToPlayToEndTimeNotification

<em>//异常中断</em>
AVPlayerItemPlaybackStalledNotification



3、系统状态

<em>//进入后台</em>
UIApplicationWillResignActiveNotification

<em>//返回前台</em>
UIApplicationDidBecomeActiveNotification
播放相关通知 1、声音类 //声音被打断的通知(电话打来) AVAudioSessionInterruptionNotification //耳机插入和拔出的通知 AVAudioSessionRouteChangeNotification 2、播放类 //播放完成 AVPlayerItemDidPlayToEndTimeNotification //播放失败 AVPlayerItemFailedToPlayToEndTimeNotification //异常中断 AVPlayerItemPlaybackStalledNotification 3、系统状态 //进入后台 UIApplicationWillResignActiveNotification //返回前台 UIApplicationDidBecomeActiveNotification

对于播放完成的通知我们可以这么写:

[[NSNotificationCenterdefaultCenter] addObserver:self selector:@selector(playerMovieFinish:) name:AVPlayerItemDidPlayToEndTimeNotificationobject:[self.player currentItem]]<em>;</em>
[[NSNotificationCenterdefaultCenter] addObserver:self selector:@selector(playerMovieFinish:) name:AVPlayerItemDidPlayToEndTimeNotificationobject:[self.player currentItem]]<em>;</em>
[[NSNotificationCenterdefaultCenter] addObserver:self selector:@selector(playerMovieFinish:) name:AVPlayerItemDidPlayToEndTimeNotificationobject:[self.player currentItem]];

提示:所有通知和 KVO 的使用我们都要记得在不用时 remove 掉。


六.猜你喜欢


ChatGPT 3.5 国内中文镜像站免费使用啦
© 版权声明
THE END
喜欢就支持一下吧
点赞2 分享
To do the useful thing, to say the courageous thing, to contemplate the beautiful thing: that’s enough for one man’s life.
做有用的事,说勇敢的话,想美好的事,一生足矣
评论 抢沙发

请登录后发表评论

    暂无评论内容