美文网首页
iOS开发-音乐播放器(简单版)

iOS开发-音乐播放器(简单版)

作者: iOS_ZZ | 来源:发表于2018-10-09 11:40 被阅读0次

    今天给同学们带来音频,音乐,和视频播放相关的案例那么废话不多说直接上代码!先看演示示例:

    iOS开发-音乐播放器(简单版).gif
    //
    
    //  ZZMusic.h
    
    //  05-音乐播放器
    
    //
    
    //  Created by 周昭 on 2017/3/20.
    
    //  Copyright © 2017年 ZZ. All rights reserved.
    
    //
    
    #warning - 对模型的处理借助MJExtension
    
    #import <Foundation/Foundation.h>
    
    @interface ZZMusic : NSObject
    
    @property (copy, nonatomic) NSString *name;
    
    @property (copy, nonatomic) NSString *filename;
    
    @property (copy, nonatomic) NSString *singer;
    
    @property (copy, nonatomic) NSString *singerIcon;
    
    @property (copy, nonatomic) NSString *icon;
    
    @property (nonatomic, assign, getter = isPlaying) BOOL playing;
    
    @end
    
    //
    
    //  ZZMusic.m
    
    //  05-音乐播放器
    
    //
    
    //  Created by 周昭 on 2017/3/20.
    
    //  Copyright © 2017年 ZZ. All rights reserved.
    
    //
    
    #import "ZZMusic.h"
    
    @implementation ZZMusic
    
    @end
    
    //
    
    //  ZZMusicCell.h
    
    //  05-音乐播放器
    
    //
    
    //  Created by 周昭 on 2017/3/20.
    
    //  Copyright © 2017年 ZZ. All rights reserved.
    
    //
    
    #import <UIKit/UIKit.h>
    
    @class  ZZMusic;
    
    @interface ZZMusicCell : UITableViewCell
    
    + (instancetype)cellWithTableView:(UITableView *)tableView;
    
    @property (nonatomic, strong) ZZMusic *music;
    
    @end
    
    //
    
    //  ZZMusicCell.m
    
    //  05-音乐播放器
    
    //
    
    //  Created by 周昭 on 2017/3/20.
    
    //  Copyright © 2017年 ZZ. All rights reserved.
    
    //
    
    #import "ZZMusicCell.h"
    
    #import "ZZMusic.h"
    
    #import "Colours.h"
    
    #import "UIImage+ZZ.h"
    
    @interface  ZZMusicCell()
    
    /**
    
     *  定时器
    
     */
    
    @property (nonatomic, strong) CADisplayLink *link;
    
    @end
    
    @implementation ZZMusicCell
    
    - (CADisplayLink *)link
    
    {
    
        if (!_link) {
    
     self.link = [CADisplayLink  displayLinkWithTarget:self  selector:@selector(update)];
    
        }
    
        return _link;
    
    }
    
    + (instancetype)cellWithTableView:(UITableView *)tableView
    
    {
    
        static NSString *ID = @"music";
    
        ZZMusicCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    
        if (cell == nil) {
    
            cell = [[ZZMusicCell  alloc] initWithStyle:UITableViewCellStyleSubtitle  reuseIdentifier:ID];
    
        }
    
        return cell;
    
    }
    
    - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
    
    {
    
        if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
    
            self.backgroundColor = [UIColor  clearColor];
    
            self.selectedBackgroundView = [[UIImageView  alloc] initWithImage:[UIImage  imageNamed:@"backgroundImage"]];
    
        }
    
     return  self;
    
    }
    
    - (void)setMusic:(ZZMusic *)music
    
    {
        _music = music;
    
        self.textLabel.text = music.name;
    
        self.detailTextLabel.text = music.singer;
    
        self.imageView.image = [UIImage  circleImageWithName:music.singerIcon  borderWidth:2  borderColor:[UIColor  skyBlueColor]];
    
        if (music.isPlaying) {
    
            [self.link  addToRunLoop:[NSRunLoop  mainRunLoop] forMode:NSDefaultRunLoopMode];
    
        } else { // 停止动画
    
            [self.link invalidate];
    
            self.link = nil;
    
         self.imageView.transform = CGAffineTransformIdentity;
    
        }
    
    }
    
    /**
    
     *  8秒转一圈, 45°/s
    
     */
    
    - (void)update
    
    {
    
     // 1/60秒 * 45
    
     // 规定时间内转动的角度 == 时间 * 速度
    
        CGFloat angle = self.link.duration * M_PI_4;
    
        self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, angle);
    
    }
    
    - (void)dealloc
    
    {
    
     // 移除定时器
    
        [self.link  removeFromRunLoop:[NSRunLoop  mainRunLoop] forMode:NSDefaultRunLoopMode];
    
    }
    
    @end
    
    //
    
    //  UIImage+ZZ.h
    
    //  05-音乐播放器
    
    //
    
    //  Created by 周昭 on 2017/3/20.
    
    //  Copyright © 2017年 ZZ. All rights reserved.
    
    //
    
    #import <UIKit/UIKit.h>
    
    @interface UIImage (ZZ)
    
    + (instancetype)circleImageWithName:(NSString *)name borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor;
    
    @end
    
    //
    
    //  UIImage+ZZ.m
    
    //  05-音乐播放器
    
    //
    
    //  Created by 周昭 on 2017/3/20.
    
    //  Copyright © 2017年 ZZ. All rights reserved.
    
    //
    
    #import "UIImage+ZZ.h"
    
    @implementation UIImage (ZZ)
    
    + (instancetype)circleImageWithName:(NSString *)name borderWidth:(CGFloat)borderWidth borderColor:(UIColor *)borderColor
    
    {
    
        // 1.加载原图
    
        UIImage *oldImage = [UIImage imageNamed:name];
    
        // 2.开启上下文
    
        CGFloat imageW = oldImage.size.width + 2 * borderWidth;
    
        CGFloat imageH = oldImage.size.height + 2 * borderWidth;
    
        CGSize imageSize = CGSizeMake(imageW, imageH);
    
        UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);
    
        // 3.取得当前的上下文
    
        CGContextRef ctx = UIGraphicsGetCurrentContext();
    
        // 4.画边框(大圆)
    
        [borderColor set];
    
        CGFloat bigRadius = imageW * 0.5; // 大圆半径
    
        CGFloat centerX = bigRadius; // 圆心
    
        CGFloat centerY = bigRadius;
    
        CGContextAddArc(ctx, centerX, centerY, bigRadius, 0, M_PI * 2, 0);
    
        CGContextFillPath(ctx); // 画圆
    
        // 5.小圆
    
        CGFloat smallRadius = bigRadius - borderWidth;
    
        CGContextAddArc(ctx, centerX, centerY, smallRadius, 0, M_PI * 2, 0);
    
        // 裁剪(后面画的东西才会受裁剪的影响)
    
        CGContextClip(ctx);
    
        // 6.画图
    
        [oldImage drawInRect:CGRectMake(borderWidth, borderWidth, oldImage.size.width, oldImage.size.height)];
    
        // 7.取图
    
       UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    
        // 8.结束上下文
    
        UIGraphicsEndImageContext();
    
        return newImage;
    
    }
    
    @end
    
    //
    
    //  ZZAudioTool.h
    
    //  05-音乐播放器
    
    //
    
    //  Created by 周昭 on 2017/3/20.
    
    //  Copyright © 2017年 ZZ. All rights reserved.
    
    //
    
    #import <Foundation/Foundation.h>
    
    #import <AVFoundation/AVFoundation.h>
    
    @interface ZZAudioTool : NSObject
    
    /**
    
     *  播放器
    
     */
    
    @property(nonatomic, strong) AVAudioPlayer *player;
    
    /**
    
     *  创建单例
    
     */
    
    + (instancetype)shareInstance;
    
    /**
    
     *  播放音效
    
     *
    
     *  @param filename 音效文件名
    
     */
    
    + (void)playSound:(NSString *)filename;
    
    /**
    
     *  销毁音效
    
     *
    
     *  @param filename 音效文件名
    
     */
    
    + (void)disposeSound:(NSString *)filename;
    
    /**
    
     *  播放音乐
    
     *
    
     *  @param filename 音乐文件名
    
     */
    
    + (AVAudioPlayer *)playMusic:(NSString *)filename;
    
    /**
    
     *  暂停音乐
    
     *
    
     *  @param filename 音乐文件名
    
     */
    
    + (void)pauseMusic:(NSString *)filename;
    
    /**
    
     *  停止音乐
    
     *
    
     *  @param filename 音乐文件名
    
     */
    
    + (void)stopMusic:(NSString *)filename;
    
    /**
    
     *  返回当前正在播放的音乐播放器
    
     */
    
    + (AVAudioPlayer *)currentPlayingAudioPlayer;
    
    @end
    
    //
    
    //  ZZAudioTool.m
    
    //  05-音乐播放器
    
    //
    
    //  Created by 周昭 on 2017/3/20.
    
    //  Copyright © 2017年 ZZ. All rights reserved.
    
    //
    
    #import "ZZAudioTool.h"
    
    @implementation ZZAudioTool
    
    /**
    
     *  存放所有的音频ID
    
     *  字典: filename作为key, soundID作为value
    
     */
    
    static  NSMutableDictionary *_soundIDDict;
    
    /**
    
     *  存放所有的音乐播放器
    
     *  字典: filename作为key, audioPlayer作为value
    
     */
    
    static NSMutableDictionary *_audioPlayerDict;
    
    /**
    
     *  返回请求单例对象
    
     */
    
    + (instancetype)shareInstance
    
    {
        static ZZAudioTool *audioTool;
    
        static dispatch_once_t onceToken;
    
        dispatch_once(&onceToken, ^{
    
            if (audioTool == nil) {
                audioTool = [[ZZAudioTool alloc] init];
            }
        });
        return audioTool;
    }
    
    /**
    
     *  初始化
    
     */
    
    + (void)initialize
    
    {
    
        _soundIDDict = [NSMutableDictionary  dictionary];
      
        _audioPlayerDict = [NSMutableDictionary  dictionary];
    
        // 设置音频会话类型
    
       AVAudioSession *session = [AVAudioSession  sharedInstance];
    
       [session setCategory:AVAudioSessionCategorySoloAmbient  error:nil];
    
       [session setActive:YES error:nil];
    
    }
    
    /**
    
     *  播放音效
    
     *
    
     *  @param filename 音效文件名
    
     */
    
    + (void)playSound:(NSString *)filename
    
    {
    
        if (!filename) return;
    
         // 1.从字典中取出soundID
    
        SystemSoundID soundID = [_soundIDDict[filename] unsignedLongValue];
    
        if (!soundID) { // 创建
    
        // 加载音效文件
    
        NSURL *url = [[NSBundle  mainBundle] URLForResource:filename withExtension:nil];
    
        if (!url) return;
    
        // 创建音效ID
    
        AudioServicesCreateSystemSoundID((__bridge  CFURLRef)url, &soundID);
    
        // 放入字典
    
        _soundIDDict[filename] = @(soundID);
    
       }
    
     // 2.播放
    
     AudioServicesPlaySystemSound(soundID);
    
    }
    
    /**
    
     *  销毁音效
    
     *
    
     *  @param filename 音效文件名
    
     */
    
    + (void)disposeSound:(NSString *)filename
    
    {
    
        if (!filename) return;
    
        SystemSoundID soundID = [_soundIDDict[filename] unsignedLongValue];
    
        if (soundID) {
    
           // 销毁音效ID
    
           AudioServicesDisposeSystemSoundID(soundID);
    
           // 从字典中移除
    
           [_soundIDDict removeObjectForKey:filename];
    
        }
    
    }
    
    /**
    
     *  播放音乐
    
     *
    
     *  @param filename 音乐文件名
    
     */
    
    + (AVAudioPlayer *)playMusic:(NSString *)filename
    
    {
    
        if (!filename) return nil;
    
     // 1.从字典中取出audioPlayer
    
        AVAudioPlayer *audioPlayer = _audioPlayerDict[filename];
    
        if (!audioPlayer) { // 创建
    
     // 加载音乐文件
    
     NSURL *url = [[NSBundle  mainBundle] URLForResource:filename withExtension:nil];
    
            if (!url) return nil;
    
     // 创建audioPlayer
    
            audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
    
            // 缓冲
    
            [audioPlayer prepareToPlay];
    
     //        audioPlayer.enableRate = YES;
    
     //        audioPlayer.rate = 10.0;
    
            // 放入字典
    
            _audioPlayerDict[filename] = audioPlayer;
    
        }
    
     // 2.播放
    
        if (!audioPlayer.isPlaying) {
    
            [audioPlayer play];
    
        }
    
        return audioPlayer;
    
    }
    
    /**
    
     *  暂停音乐
    
     *
    
     *  @param filename 音乐文件名
    
     */
    
    + (void)pauseMusic:(NSString *)filename
    
    {
    
        if (!filename) return;
    
     // 1.从字典中取出audioPlayer
    
        AVAudioPlayer *audioPlayer = _audioPlayerDict[filename];
    
     // 2.暂停
    
        if (audioPlayer.isPlaying) {
    
            [audioPlayer pause];
    
        }
    
    }
    
    /**
    
     *  停止音乐
    
     *
    
     *  @param filename 音乐文件名
    
     */
    
    + (void)stopMusic:(NSString *)filename
    
    {
    
        if (!filename) return;
    
     // 1.从字典中取出audioPlayer
    
        AVAudioPlayer *audioPlayer = _audioPlayerDict[filename];
    
     // 2.暂停
    
        if (audioPlayer.isPlaying) {
    
            [audioPlayer stop];
    
            // 直接销毁
    
            [_audioPlayerDict removeObjectForKey:filename];
    
        }
    
    }
    
    /**
    
     *  返回当前正在播放的音乐播放器
    
     */
    
    + (AVAudioPlayer *)currentPlayingAudioPlayer
    
    {
    
        for (NSString *filename in _audioPlayerDict) {
    
            AVAudioPlayer *audioPlayer = _audioPlayerDict[filename];
    
            if (audioPlayer.isPlaying) {
    
                return audioPlayer;
    
            }
    
        }
    
     return  nil;
    
    }
    
    @end
    
    //
    
    //  ZZMusicsController.h
    
    //  05-音乐播放器
    
    //
    
    //  Created by 周昭 on 2017/3/20.
    
    //  Copyright © 2017年 ZZ. All rights reserved.
    
    //
    
    #import <UIKit/UIKit.h>
    
    @interface ZZMusicsController : UIViewController
    
    @end
    
    //
    
    //  ZZMusicsController.m
    
    //  05-音乐播放器
    
    //
    
    //  Created by 周昭 on 2017/3/20.
    
    //  Copyright © 2017年 ZZ. All rights reserved.
    
    //
    
    #import "ZZMusicsController.h"
    
    #import "ZZMusic.h"
    
    #import "ZZMusicCell.h"
    
    #import "ZZAudioTool.h"
    
    #import "MJExtension.h"
    
    #import "NSString+ZZ.h"
    
    #import <AVFoundation/AVFoundation.h>
    
    #import <MediaPlayer/MediaPlayer.h>
    
    @interface  ZZMusicsController ()<UITableViewDelegate,UITableViewDataSource,AVAudioPlayerDelegate>
    
    @property (nonatomic, strong) NSArray *musics;
    
    @property (nonatomic, strong) AVAudioPlayer *currentPlayingAudioPlayer;
    
    @property (nonatomic, weak) UITableView *tableView;
    
    @property (nonatomic, weak) UIImageView *imgView;
    
    @end
    
    @implementation ZZMusicsController
    
    #pragma mark - 懒加载
    
    - (NSArray *)musics
    
    {
    
        if (!_musics) {
    
     self.musics = [ZZMusic  objectArrayWithFilename:@"Musics.plist"];
    
        }
    
     return  _musics;
    
    }
    
    - (void)viewDidLoad {
    
        [super  viewDidLoad];
    
     // 0.设置标题&背景
    
        [self  setUpTitle];
    
     // 1.初始化tableView
    
        [self  setUpTableView];
    
    }
    
    #pragma mark - setUp 初始化
    
    - (void)setUpTableView
    
    {
    
     // 0.创建tableView
    
        UITableView *tableView = [[UITableView alloc] init];
    
        tableView.delegate = self;
    
        tableView.dataSource = self;
    
        tableView.tableFooterView = [[UIView alloc] init];
    
     // 1.设置背景
    
        UIImageView *imgView = [[UIImageView alloc] init];
    
        imgView.frame = self.view.frame;
    
        imgView.image = [UIImage imageNamed:@"backgroundImage"];
    
        tableView.backgroundView = imgView;
    
        tableView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    
        [self.view addSubview:tableView];
    
        self.tableView = tableView;
    
    }
    
    - (void)setUpTitle
    
    {
    
     // 0.设置标题
    
     self.title = NSLocalizedString(@"音乐播放器", nil);
    
    }
    
    #pragma mark - Table view data source
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    
    {
    
     return  self.musics.count;
    
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    
    {
    
     // 1.创建cell
    
        ZZMusicCell *cell = [ZZMusicCell cellWithTableView:tableView];
    
     // 2.设置cell的数据
    
        cell.music = self.musics[indexPath.row];
    
        return cell;
    
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    
    {
    
        return 70;
    
    }
    
    - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
    
    {
    
     // 停止音乐
    
        ZZMusic *music = self.musics[indexPath.row];
    
        [ZZAudioTool  stopMusic:music.filename];
    
     // 再次传递模型
    
        ZZMusicCell *cell = (ZZMusicCell *)[tableView cellForRowAtIndexPath:indexPath];
    
        music.playing = NO;
    
        cell.music = music;
    
    }
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    
    {
    
     // 取出当前点击的cell
    
        ZZMusicCell *cell = (ZZMusicCell *)[tableView cellForRowAtIndexPath:indexPath];
    
     // 取出要播放的音乐
    
        ZZMusic *music = self.musics[indexPath.row];
    
        if (music.playing) {
    
            [ZZAudioTool pauseMusic:music.filename];
    
            music.playing = NO;
    
            cell.music = music;
    
        } else {
    
            AVAudioPlayer *audioPlayer = [ZZAudioTool playMusic:music.filename];
    
            audioPlayer.delegate = self;
    
     self.currentPlayingAudioPlayer = audioPlayer;
    
     // 在锁屏界面显示歌曲信息
    
            [self  showInfoInLockedScreen:music];
    
     // 再次传递模型
    
            music.playing = YES;
    
            cell.music = music;
    
        }
    
    }
    
    /**
    
     *  在锁屏界面显示歌曲信息
    
     */
    
    - (void)showInfoInLockedScreen:(ZZMusic *)music
    
    {
    
     NSMutableDictionary *info = [NSMutableDictionary  dictionary];
    
     // 标题(音乐名称)
    
        info[MPMediaItemPropertyTitle] = music.name;
    
     // 作者
    
        info[MPMediaItemPropertyArtist] = music.singer;
    
     // 专辑
    
        info[MPMediaItemPropertyAlbumTitle] = music.singer;
    
     // 图片
    
        info[MPMediaItemPropertyArtwork] = [[MPMediaItemArtwork  alloc] initWithImage:[UIImage  imageNamed:music.icon]];
    
        [MPNowPlayingInfoCenter  defaultCenter].nowPlayingInfo = info;
    
    }
    
    #pragma mark - AVAudioPlayerDelegate
    
    - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
    
    {
    
     // 计算下一行
    
        NSIndexPath *selectedPath = [self.tableView indexPathForSelectedRow];
    
        NSInteger nextRow = selectedPath.row + 1;
    
        if (nextRow == self.musics.count) {
    
            nextRow = 0;
    
        }
    
    #warning 停止上一首歌的转圈
    
     // 再次传递模型
    
        ZZMusicCell *cell = (ZZMusicCell *)[self.tableView cellForRowAtIndexPath:selectedPath];
    
        ZZMusic *music = self.musics[selectedPath.row];
    
        music.playing = NO;
    
        cell.music = music;
    
     // 播放下一首歌
    
        NSIndexPath *currentPath = [NSIndexPath indexPathForRow:nextRow inSection:selectedPath.section];
    
        [self.tableView  selectRowAtIndexPath:currentPath animated:YES  scrollPosition:UITableViewScrollPositionTop];
    
        [self  tableView:self.tableView  didSelectRowAtIndexPath:currentPath];
    
    }
    
    /**
    
     *  音乐播放器被打断(打\接电话)
    
     */
    
    - (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player
    
    {
    
     NSLog(@"audioPlayerBeginInterruption---被打断");
    
    }
    
    /**
    
     *  音乐播放器停止打断(打\接电话)
    
     */
    
    - (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withOptions:(NSUInteger)flags
    
    {
    
     NSLog(@"audioPlayerEndInterruption---停止打断");
    
        [player play];
    
    }
    @end
    

    相关文章

      网友评论

          本文标题:iOS开发-音乐播放器(简单版)

          本文链接:https://www.haomeiwen.com/subject/apseaftx.html