iOS之基于FreeStreamer的简单音乐播放器示例

2020-01-21 02:24:13于海丽

在上面的代码中,有许多逻辑是后面加的,比如更新UI界面,获取歌词等处理,如果要实现简单的播放,则可以不用重写该方法,直接通过playFromURL就可以实现我们的播放功能。

2、更新UI

这里的UI暂不包括歌词的更新,而只是进度条的更新,要更新进度条,比不可少的是定时器,这里我没有选择NSTimer,而是选择了CADisplayLink,至于为什么,我想大家应该都比较了解,可以这么来对比,下面引用一段其他博客的对比:

iOS设备的屏幕刷新频率是固定的,CADisplayLink在正常情况下会在每次刷新结束都被调用,精确度相当高。

NSTimer的精确度就显得低了点,比如NSTimer的触发时间到的时候,runloop如果在阻塞状态,触发时间就会推迟到下一个runloop周期。并且 NSTimer新增了tolerance属性,让用户可以设置可以容忍的触发的时间的延迟范围。

CADisplayLink使用场合相对专一,适合做UI的不停重绘,比如自定义动画引擎或者视频播放的渲染。NSTimer的使用范围要广泛的多,各种需要单次或者循环定时处理的任务都可以使用。在UI相关的动画或者显示内容使用 CADisplayLink比起用NSTimer的好处就是我们不需要在格外关心屏幕的刷新频率了,因为它本身就是跟屏幕刷新同步的

使用方法


 if (!_progressTimer) {
    _progressTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateProgress)];
    [_progressTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
  }

更新进度


- (void)updateProgress
{
  if (self.glPlayerDelegate && [self.glPlayerDelegate respondsToSelector:@selector(updateProgressWithCurrentPosition:endPosition:)])
  {
    [self.glPlayerDelegate updateProgressWithCurrentPosition:self.currentTimePlayed endPosition:self.duration];
  }
  
  [self showLockScreenCurrentTime:(self.currentTimePlayed.second + self.currentTimePlayed.minute * 60) totalTime:(self.duration.second + self.duration.minute * 60)];
}

在这里有两个属性:currentTimePlayed和duration,分别保存着当前播放时间和总时间,是如下的结构体


typedef struct {
  unsigned minute;
  unsigned second;
  
  /**
   * Playback time in seconds.
   */
  float playbackTimeInSeconds;
  
  /**
   * Position within the stream, where 0 is the beginning
   * and 1.0 is the end.
   */
  float position;
} FSStreamPosition;

我们在更新UI的时候,主要可以根据其中的minute和second来,如果播放了90s,那么minute就为1,而second为30,所以我们在计算的时候,应该是这样的(self.currentTimePlayed.second + self.currentTimePlayed.minute * 60)

当然在更新进度条的时候,我们也可以通过position直接来给slider进行赋值,这表示当前播放的比例