zoukankan      html  css  js  c++  java
  • MEDIA-SYSSERVICES媒体播放

    1 简单的音乐播放器

    1.1 问题

    本案例结合之前所学的网络和数据解析等知识完成一个网络音乐播放器,如图-1所示:

    图-1

    1.2 方案

    首先创建一个SingleViewApplication应用,在Storyboard文件中搭建音乐播放器界面,该应用有三个场景组成,第一个场景用于搜索,第二场景显示歌曲列表,第三个场景是播放歌曲界面,有一个播放进度条。这三个场景由一个导航视图控制器管理,如图-2所示:

    图-2

    本案例使用一个百度的音乐开放接口http://mp3.baidu.com,首先创建一个模型类TRMusicInfo存放音乐的相关信息。

    其次将网络请求和解析的代码封装在两个类中TRWebUtils和TRParser。TRWebUtils类中有两个方法,一个是requestMusicsByWord:andCallBack:,该方法根据用户输入的歌手姓名获取到网络请求的路径,然后采用NSURLConnection类发送异步请求,返回的数据是Json格式的,然后采用NSJSONSerialization类进行Json解析,得到音乐的相关信息。

    TRWebUtils类中的另一个方法requestMusicDetailByMusic:andCallBack,该方法是通过音乐信息中的音乐ID发送网络请求,然后通过数据解析获取到音乐的下载的地址和歌词地址。对应的在TRParser类有两个解析数据的方法parseMusicInfoByArray:和parseMusicDetailByDic:andMusic:。

    然后完成音乐列表视图控制器TRMusicListViewController的代码,该视图控制器继承至UITableViewController,有一个NSMutableArray类型的属性musics,用于存放需要展示的音乐信息。在viewDidLoad方法中通过TRWebUtils类调用requestMusicsByWord:andCallBack:方法,根据用户输入的歌手姓名发送网络请求,解析歌曲数据得到属性self.music数据,刷新界面。

    由于表视图的每个Cell需要展示歌曲的信息,所以这里需要自定义一个Cell,因此创建一个TRMusicCell类,继承至UITableViewCell类,需要显示专辑封面,歌曲名、歌手名以及专辑名,如图-3所示:

    图-3

    然后实现音乐播放视图控制器TRPlayViewController的代码,该视图控制器有一个TRMusicInfo类型的公开属性music,用于记录用户从上一个界面选择的音乐信息。

    该视图控制器还有如下几个私有属性:

    AVAudioPlayer类型的player,用于播放音乐;

    NSURLConnection类型的conn,用于发送下载请求;

    NSMutableData类型的allData,用于存放下载的音乐数据;

    NSUInteger类型的fileLength,用于记录下载音乐的大小;

    在TRPlayViewController的viewDidLoad方法中通过TRWebUtils类调用requestMusicDetailByMusic:andCallBack:方法,根据音乐信息获取到音乐的下载地址和歌词地址,然后通过音乐下载地址发送下载请求,将发送下载请求的代码封装在downloadMusic方法中。

    接下来实现NSURLConnectionDelegate的协议方法,在connection:didReceiveResponse:方法中解析头文件,获取到文件的大小并初始化self.allData属性。

    在connection:didReceiveData:方法中将下载到的音乐数据保存在self.allData中,并且创建音乐播放器并播放歌曲,实现边下载边播放的功能。

    在connectionDidFinishLoading:方法中将音乐的数据存入本地。

    最后开启一个计时器,更新进度条的显示,即音乐的播放进度。

    1.3 步骤

    实现此案例需要按照如下步骤进行。

    步骤一:创建模型类

    首先创建一个SingleViewApplication应用,在Storyboard文件中搭建音乐播放器界面,该应用有三个场景组成,第一个场景用于搜索,第二场景显示歌曲列表,第三个场景是播放歌曲界面,有一个播放进度条。

    本案例使用一个百度的音乐开放接口http://mp3.baidu.com,首先创建一个模型类TRMusicInfo存放音乐的相关信息,代码如下所示:

    @interface TRMusicInfo : NSObject
    @property (nonatomic, copy)NSString *name;
    @property (nonatomic, copy)NSString *singerName;
    @property (nonatomic, copy)NSString *albumName;
    @property (nonatomic, copy)NSString *songID;
    @property (nonatomic, copy)NSString *albumImagePath;
    @property (nonatomic, copy)NSString *musicPath;
    @property (nonatomic, copy)NSString *lrcPath;
    @end
     
      1 其次将网络请求和解析的代码封装在两个类中TRWebUtils和TRParser。TRWebUtils类中有两个方法,一个是requestMusicsByWord:andCallBack:,该方法根据用户输入的歌手姓名获取到网络请求的路径,然后采用NSURLConnection类发送异步请求,返回的数据是Json格式的,然后采用NSJSONSerialization类进行Json解析,得到音乐的相关信息,代码如下所示:
      2 
      3 + (void)requestMusicsByWord:(NSString *)word andCallBack:(MyCallback)callback{
      4 NSString *path = [NSString stringWithFormat:@"http://mp3.baidu.com/dev/api/?tn=getinfo&ct=0&word=%@&ie=utf-8&format=json",word];
      5 path = [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
      6 NSURL *url = [NSURL URLWithString:path];
      7 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
      8 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
      9 NSArray *arr = [NSJSONSerialization JSONObjectWithData:data options:0 error:Nil];
     10 if (arr.count==0) {
     11 [TRWebUtils requestMusicsByWord:word andCallBack:callback];
     12 }
     13 NSMutableArray *musics = [TRParser parseMusicInfoByArray:arr];
     14 callback(musics);
     15 }];
     16 }
     17 TRWebUtils类中的另一个方法requestMusicDetailByMusic:andCallBack,该方法是通过音乐信息中的音乐ID发送网络请求,然后通过数据解析获取到音乐的下载的地址和歌词地址,代码如下所示:
     18 
     19 + (void)requestMusicDetailByMusic:(TRMusicInfo *)music andCallBack:(MyCallback)callback{
     20 NSString *path = [NSString stringWithFormat:@"http://ting.baidu.com/data/music/links?songIds=%@",music.songID];
     21 NSLog(@"%@",path);
     22 NSURL *url = [NSURL URLWithString:path];
     23 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
     24 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
     25 NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:Nil];
     26 [TRParser parseMusicDetailByDic:dic andMusic:music];
     27 callback(music);
     28 }];
     29 }
     30 对应的在TRParser类有两个解析数据的方法parseMusicInfoByArray:和parseMusicDetailByDic:andMusic:,代码如下所示:
     31 
     32 +(NSMutableArray *)parseMusicInfoByArray:(NSArray *)arr{
     33 NSMutableArray *musics = [NSMutableArray array];
     34 for (NSDictionary *musicDic in arr) {
     35 TRMusicInfo *mi = [[TRMusicInfo alloc]init];
     36 mi.name = [musicDic objectForKey:@"song"];
     37 mi.singerName = [musicDic objectForKey:@"singer"];
     38 mi.albumName = [musicDic objectForKey:@"album"];
     39 mi.songID = [musicDic objectForKey:@"song_id"];
     40 mi.albumImagePath = [musicDic objectForKey:@"albumPicSmall"];
     41 [musics addObject:mi];
     42 }
     43 return musics;
     44 }
     45 +(void)parseMusicDetailByDic:(NSDictionary *)dic andMusic:(TRMusicInfo *)music{
     46 NSDictionary *dataDic = [dic objectForKey:@"data"];
     47 NSArray *songListArr = [dataDic objectForKey:@"songList"];
     48 NSDictionary *musicDic = [songListArr lastObject];
     49 NSString *musicPath = [musicDic objectForKey:@"showLink"];
     50 music.musicPath = musicPath;
     51 music.lrcPath = [NSString stringWithFormat:@"http://ting.baidu.com%@",[musicDic objectForKey:@"lrcLink"]];
     52 }
     53 步骤二:实现TRMusicListViewController展示音乐列表功能
     54 
     55 音乐列表视图控制器TRMusicListViewController继承至UITableViewController,它有一个NSMutableArray类型的属性musics,用于存放需要展示的音乐信息。
     56 
     57 在viewDidLoad方法中通过TRWebUtils类调用requestMusicsByWord:andCallBack:方法,根据用户输入的歌手姓名发送网络请求,解析歌曲数据得到属性self.music数据,刷新界面,代码如下所示:
     58 
     59 - (void)viewDidLoad
     60 {
     61 [super viewDidLoad];
     62 [TRWebUtils requestMusicsByWord:self.word andCallBack:^(id obj) {
     63 self.musics = obj;
     64 [self.tableView reloadData];
     65 }];
     66 }
     67 用户所挑选的图片将呈现在下方的ScrollView上面,因此需要在弹出ImagePickerController时创建一个ScrollView和一个确定按钮,当点击确定按钮时表示用户完成图片选择,返回之前的界面,该功能需要在navigationController:didShowViewController:animated:方法中实现,代码如下所示:
     68 
     69 -(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
     70 //创建确定按钮
     71 UIImageView *iv = [[UIImageView alloc]initWithFrame:CGRectMake(0, 450, 320, 20)];
     72 [iv setBackgroundColor:[UIColor yellowColor]];
     73 UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
     74 btn.frame = CGRectMake(270, 0, 50, 20);
     75 [btn setTitle:@"确定" forState:UIControlStateNormal];
     76 [btn addTarget:self action:@selector(finishPickImage) forControlEvents:UIControlEventTouchUpInside];
     77 btn.tag = 1;
     78 [iv addSubview:btn];
     79 iv.userInteractionEnabled = YES;
     80 [viewController.view addSubview:iv];
     81 //创建呈现挑选图片的ScrollView
     82 self.pickerScrollView = [[UIScrollView alloc]init];
     83 self.pickerScrollView.frame = CGRectMake(0, 470, 320,80);
     84 [self.pickerScrollView setBackgroundColor:[UIColor grayColor]];
     85 [viewController.view addSubview:self.pickerScrollView];
     86 }
     87 于表视图的每个Cell需要展示歌曲的信息,所以这里需要自定义一个Cell,因此创建一个TRMusicCell类,继承至UITableViewCell类,需要显示专辑封面,歌曲名、歌手名以及专辑名,代码如下所示:
     88 
     89 //TRMusicCell.h
     90 @interface TRMusicCell : UITableViewCell
     91 @property (weak, nonatomic) IBOutlet UILabel *singerLabel;
     92 @property (weak, nonatomic) IBOutlet UIImageView *albumIV;
     93 @property (weak, nonatomic) IBOutlet UILabel *nameLabel;
     94 @property (weak, nonatomic) IBOutlet UILabel *albumLabel;
     95 @property (nonatomic, strong)TRMusicInfo *music;
     96 @end
     97 //TRMusicCell.m
     98 @implementation TRMusicCell
     99 -(void)layoutSubviews{
    100 [super layoutSubviews];
    101 self.nameLabel.text = self.music.name;
    102 self.singerLabel.text = self.music.singerName;
    103 self.albumLabel.text = self.music.albumName;
    104 NSLog(@"%@",self.music.albumImagePath);
    105 //从网络获取图片比较耗时,将此操作放入一个操作队列异步执行
    106 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    107 NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.music.albumImagePath]];
    108 UIImage *image = [UIImage imageWithData:imageData];
    109 dispatch_async(dispatch_get_main_queue(), ^{
    110 self.albumIV.image = image;
    111 });
    112 });
    113 }
    114 @end
    115 最后实现表视图的数据源方法和delegate委托方法,代码如下所示:
    116 
    117 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    118 {
    119 return self.musics.count;
    120 }
    121 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    122 {
    123 static NSString *CellIdentifier = @"Cell";
    124 TRMusicCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    125 TRMusicInfo *music = self.musics[indexPath.row];
    126 cell.music = music;
    127 return cell;
    128 }
    129 //当用户选择某一首歌曲的时候跳转到音乐播放界面
    130 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    131 TRMusicInfo *m = self.musics[indexPath.row];
    132 [self performSegueWithIdentifier:@"playvc" sender:m];
    133 }
    134 步骤三:实现TRPlayViewController的音乐下载和播放功能
    135 
    136 音乐播放视图控制器TRPlayViewController有一个TRMusicInfo类型的公开属性music,用于记录用户从上一个界面选择的音乐信息,代码如下所示:
    137 
    138 @interface TRPlayViewController : UIViewController
    139 @property (nonatomic, strong)TRMusicInfo *music;
    140 @end
    141 该视图控制器的私有属性,代码如下所示:
    142 
    143 @interface TRPlayViewController ()
    144 @property (weak, nonatomic) IBOutlet UISlider *mySlider;
    145 @property (nonatomic, strong)NSMutableData *allData;
    146 @property (nonatomic, strong)AVAudioPlayer *player;
    147 @property (nonatomic, strong)NSTimer *myTimer;
    148 @property (nonatomic, strong) NSURLConnection *conn;
    149 @property (nonatomic) NSUInteger fileLength;
    150 @end
    151 其次在TRPlayViewController的viewDidLoad方法中通过TRWebUtils类调用requestMusicDetailByMusic:andCallBack:方法,根据音乐信息获取到音乐的下载地址和歌词地址,代码如下所示:
    152 
    153 - (void)viewDidLoad
    154 {
    155 [super viewDidLoad];
    156 [TRWebUtils requestMusicDetailByMusic:self.music andCallBack:^(id obj) {
    157 [self downloadMusic];
    158 }];
    159 }
    160 然后通过音乐下载地址发送下载请求,将发送下载请求的代码封装在downloadMusic方法中,代码如下所示:
    161 
    162 -(void)downloadMusic{
    163 NSURL *url = [NSURL URLWithString:self.music.musicPath];
    164 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    165 //对象创建出来时异步请求已经发出
    166 self.conn = [[NSURLConnection alloc]initWithRequest:request delegate:self];
    167 if (!self.conn) {
    168 NSLog(@"链接创建失败");
    169 }
    170 }
    171 接下来实现NSURLConnectionDelegate的协议方法,在connection:didReceiveResponse:方法中解析头文件,获取到文件的大小并初始化self.allData属性,代码如下所示:
    172 
    173 //接收到服务器响应
    174 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    175 NSHTTPURLResponse *res = (NSHTTPURLResponse*)response;
    176 NSDictionary *headerDic = res.allHeaderFields;
    177 NSLog(@"%@",headerDic);
    178 self.fileLength = [[headerDic objectForKey:@"Content-Length"] intValue];
    179 self.allData = [NSMutableData data];
    180 }
    181 在connection:didReceiveData:方法中将下载到的音乐数据保存在self.allData中,并且创建音乐播放器并播放歌曲,实现边下载边播放的功能,代码如下所示:
    182 
    183 //接收到数据
    184 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    185 // NSLog(@"%d",data.length);
    186 [self.allData appendData:data];
    187 //初始化player对象
    188 if (self.allData.length>1024*150&&!self.player) {
    189 NSLog(@"开始播放");
    190 self.player = [[AVAudioPlayer alloc]initWithData:self.allData error:Nil];
    191 [self.player play];
    192 float allTime = self.player.duration*self.fileLength/self.allData.length;
    193 self.mySlider.maximumValue = allTime;
    194 }
    195 }
    196 在connectionDidFinishLoading:方法中将音乐的数据存入本地,代码如下所示:
    197 
    198 //加载完成
    199 -(void)connectionDidFinishLoading:(NSURLConnection *)connection{
    200 NSLog(@"下载完成");
    201 //下载完成之后更新准确的歌曲时长
    202 self.mySlider.maximumValue = self.player.duration;
    203 NSString *filePath = [NSString stringWithFormat:@"/Users/Vivian/Desktop/%@",self.music.name];
    204 filePath = [filePath stringByAppendingPathExtension:@"mp3"];
    205 [self.allData writeToFile:filePath atomically:YES];
    206 }
    207 最后在downloadMusic方法中开启一个计时器,更新进度条的显示,即音乐的播放进度,代码如下所示:
    208 
    209  
    210 -(void)downloadMusic{
    211 NSURL *url = [NSURL URLWithString:self.music.musicPath];
    212 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    213 //对象创建出来时异步请求已经发出
    214 self.conn = [[NSURLConnection alloc]initWithRequest:request delegate:self];
    215 if (!self.conn) {
    216 NSLog(@"链接创建失败");
    217 }
    218 //开启一个计时器,更新界面的进度条
    219 self.myTimer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(updateUI) userInfo:Nil repeats:YES];
    220 }
    221 -(void)viewDidDisappear:(BOOL)animated{
    222 [self.myTimer invalidate];
    223 }
    224 -(void)updateUI{
    225 self.mySlider.value = self.player.currentTime;
    226 }
    227 1.4 完整代码
    228 
    229 本案例中,TRViewController.m文件中的完整代码如下所示:
    230 
    231  
    232 #import "TRViewController.h"
    233 #import "TRMusicListViewController.h"
    234 @interface TRViewController ()
    235 @property (weak, nonatomic) IBOutlet UITextField *myTF;
    236 @end
    237 @implementation TRViewController
    238 -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    239 TRMusicListViewController *vc = segue.destinationViewController;
    240 vc.word = self.myTF.text;
    241 }
    242 @end
    243  
    244 本案例中,TRMusicListViewController.h文件中的完整代码如下所示:
    245 
    246  
    247 #import <UIKit/UIKit.h>
    248 @interface TRMusicListViewController : UITableViewController
    249 @property (nonatomic, copy)NSString *word;
    250 @end
    251  
    252 本案例中,TRMusicListViewController.m文件中的完整代码如下所示:
    253 
    254  
    255 #import "TRMusicCell.h"
    256 #import "TRMusicListViewController.h"
    257 #import "TRParser.h"
    258 #import "TRMusicInfo.h"
    259 #import "TRWebUtils.h"
    260 #import "TRPlayViewController.h"
    261 @interface TRMusicListViewController ()
    262 @property (nonatomic, strong)NSMutableArray *musics;
    263 @end
    264 @implementation TRMusicListViewController
    265 - (void)viewDidLoad
    266 {
    267 [super viewDidLoad];
    268 [TRWebUtils requestMusicsByWord:self.word andCallBack:^(id obj) {
    269 self.musics = obj;
    270 [self.tableView reloadData];
    271 }];
    272 }
    273 #pragma mark - Table view data source
    274 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    275 {
    276 return self.musics.count;
    277 }
    278 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    279 {
    280 static NSString *CellIdentifier = @"Cell";
    281 TRMusicCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    282 TRMusicInfo *music = self.musics[indexPath.row];
    283 cell.music = music;
    284 return cell;
    285 }
    286 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    287 TRMusicInfo *m = self.musics[indexPath.row];
    288 [self performSegueWithIdentifier:@"playvc" sender:m];
    289 }
    290 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    291 {
    292 TRPlayViewController *vc = segue.destinationViewController;
    293 vc.music = sender;
    294 }
    295 @end
    296  
    297 本案例中,TRPlayViewController.h文件中的完整代码如下所示:
    298 
    299  
    300 #import <UIKit/UIKit.h>
    301 #import "TRMusicInfo.h"
    302 @interface TRPlayViewController : UIViewController
    303 @property (nonatomic, strong)TRMusicInfo *music;
    304 @end
    305  
    306 本案例中,TRPlayViewController.m文件中的完整代码如下所示:
    307 
    308  
    309 #import "TRPlayViewController.h"
    310 #import "TRWebUtils.h"
    311 #import <AVFoundation/AVFoundation.h>
    312 @interface TRPlayViewController ()
    313 @property (weak, nonatomic) IBOutlet UISlider *mySlider;
    314 @property (nonatomic, strong)NSMutableData *allData;
    315 @property (nonatomic, strong)AVAudioPlayer *player;
    316 @property (nonatomic, strong)NSTimer *myTimer;
    317 @property (nonatomic, strong) NSURLConnection *conn;
    318 @property (nonatomic) NSUInteger fileLength;
    319 @end
    320 @implementation TRPlayViewController
    321 - (void)viewDidLoad
    322 {
    323 [super viewDidLoad];
    324 [TRWebUtils requestMusicDetailByMusic:self.music andCallBack:^(id obj) {
    325 [self downloadMusic];
    326 }];
    327 }
    328 -(void)downloadMusic{
    329 NSURL *url = [NSURL URLWithString:self.music.musicPath];
    330 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    331 //对象创建出来时 异步请求已经发出
    332 self.conn = [[NSURLConnection alloc]initWithRequest:request delegate:self];
    333 if (!self.conn) {
    334 NSLog(@"链接创建失败");
    335 }
    336 //开启一个计时器,更新界面的进度条
    337 self.myTimer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(updateUI) userInfo:Nil repeats:YES];
    338 }
    339 -(void)viewDidDisappear:(BOOL)animated{
    340 [self.myTimer invalidate];
    341 }
    342 -(void)updateUI{
    343 self.mySlider.value = self.player.currentTime;
    344 }
    345 #pragma mark NSURLConnectionDelegate
    346 //接收到服务器响应
    347 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    348 NSHTTPURLResponse *res = (NSHTTPURLResponse*)response;
    349 NSDictionary *headerDic = res.allHeaderFields;
    350 NSLog(@"%@",headerDic);
    351 self.fileLength = [[headerDic objectForKey:@"Content-Length"] intValue];
    352 self.allData = [NSMutableData data];
    353 }
    354 //接收到数据
    355 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    356 // NSLog(@"%d",data.length);
    357 [self.allData appendData:data];
    358 //初始化player对象
    359 if (self.allData.length>1024*150&&!self.player) {
    360 NSLog(@"开始播放");
    361 self.player = [[AVAudioPlayer alloc]initWithData:self.allData error:Nil];
    362 [self.player play];
    363 float allTime = self.player.duration*self.fileLength/self.allData.length;
    364 self.mySlider.maximumValue = allTime;
    365 }
    366 }
    367 //加载完成
    368 -(void)connectionDidFinishLoading:(NSURLConnection *)connection{
    369 NSLog(@"下载完成");
    370 //下载完成之后更新准确的歌曲时长
    371 self.mySlider.maximumValue = self.player.duration;
    372 NSString *filePath = [NSString stringWithFormat:@"/Users/Vivian/Desktop/%@",self.music.name];
    373 filePath = [filePath stringByAppendingPathExtension:@"mp3"];
    374 [self.allData writeToFile:filePath atomically:YES];
    375 }
    376 @end
    377  
    378 本案例中,TRMusicCell.h文件中的完整代码如下所示:
    379 
    380  
    381 #import <UIKit/UIKit.h>
    382 #import "TRMusicInfo.h"
    383 @interface TRMusicCell : UITableViewCell
    384 @property (weak, nonatomic) IBOutlet UILabel *singerLabel;
    385 @property (weak, nonatomic) IBOutlet UIImageView *albumIV;
    386 @property (weak, nonatomic) IBOutlet UILabel *nameLabel;
    387 @property (weak, nonatomic) IBOutlet UILabel *albumLabel;
    388 @property (nonatomic, strong)TRMusicInfo *music;
    389 @end
    390  
    391 本案例中,TRMusicCell.m文件中的完整代码如下所示:
    392 
    393  
    394 @implementation TRMusicCell
    395 -(void)layoutSubviews{
    396 [super layoutSubviews];
    397 self.nameLabel.text = self.music.name;
    398 self.singerLabel.text = self.music.singerName;
    399 self.albumLabel.text = self.music.albumName;
    400 NSLog(@"%@",self.music.albumImagePath);
    401 //从网络获取图片比较耗时,将此操作放入一个操作队列异步执行
    402 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    403 NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.music.albumImagePath]];
    404 UIImage *image = [UIImage imageWithData:imageData];
    405 dispatch_async(dispatch_get_main_queue(), ^{
    406 self.albumIV.image = image;
    407 });
    408 });
    409 }
    410 @end
    411  
    412 本案例中,TRMusicInfo.h文件中的完整代码如下所示:
    413 
    414  
    415 #import <Foundation/Foundation.h>
    416 @interface TRMusicInfo : NSObject
    417 @property (nonatomic, copy)NSString *name;
    418 @property (nonatomic, copy)NSString *singerName;
    419 @property (nonatomic, copy)NSString *albumName;
    420 @property (nonatomic, copy)NSString *songID;
    421 @property (nonatomic, copy)NSString *albumImagePath;
    422 @property (nonatomic, copy)NSString *musicPath;
    423 @property (nonatomic, copy)NSString *lrcPath;
    424 @end
    425  
    426 本案例中,TRParser.h文件中的完整代码如下所示:
    427 
    428  
    429 #import <Foundation/Foundation.h>
    430 #import "TRMusicInfo.h"
    431 @interface TRParser : NSObject
    432 + (NSMutableArray *)parseMusicInfoByArray:(NSArray *)arr;
    433 + (void)parseMusicDetailByDic:(NSDictionary *)dic andMusic:(TRMusicInfo *)music;
    434 @end
    435  
    436 本案例中,TRParser.m文件中的完整代码如下所示:
    437 
    438  
    439 #import "TRParser.h"
    440 #import "TRMusicInfo.h"
    441 @implementation TRParser
    442 +(NSMutableArray *)parseMusicInfoByArray:(NSArray *)arr{
    443 NSMutableArray *musics = [NSMutableArray array];
    444 for (NSDictionary *musicDic in arr) {
    445 TRMusicInfo *mi = [[TRMusicInfo alloc]init];
    446 mi.name = [musicDic objectForKey:@"song"];
    447 mi.singerName = [musicDic objectForKey:@"singer"];
    448 mi.albumName = [musicDic objectForKey:@"album"];
    449 mi.songID = [musicDic objectForKey:@"song_id"];
    450 mi.albumImagePath = [musicDic objectForKey:@"albumPicSmall"];
    451 [musics addObject:mi];
    452 }
    453 return musics;
    454 }
    455 +(void)parseMusicDetailByDic:(NSDictionary *)dic andMusic:(TRMusicInfo *)music{
    456 NSDictionary *dataDic = [dic objectForKey:@"data"];
    457 NSArray *songListArr = [dataDic objectForKey:@"songList"];
    458 NSDictionary *musicDic = [songListArr lastObject];
    459 NSString *musicPath = [musicDic objectForKey:@"showLink"];
    460 music.musicPath = musicPath;
    461 music.lrcPath = [NSString stringWithFormat:@"http://ting.baidu.com%@",[musicDic objectForKey:@"lrcLink"]];
    462 }
    463 @end
    464  
    465 本案例中,TRWebUtils.h文件中的完整代码如下所示:
    466 
    467  
    468 #import <Foundation/Foundation.h>
    469 #import "TRMusicInfo.h"
    470 typedef void (^MyCallback)(id obj);
    471 @interface TRWebUtils : NSObject
    472 + (void)requestMusicsByWord:(NSString *)word andCallBack:(MyCallback)callback;
    473 + (void)requestMusicDetailByMusic:(TRMusicInfo *)music andCallBack:(MyCallback)callback;
    474 @end
    475  
    476 本案例中,TRWebUtils.m文件中的完整代码如下所示:
    477 
    478  
    479 #import "TRWebUtils.h"
    480 #import "TRParser.h"
    481 @implementation TRWebUtils
    482 + (void)requestMusicsByWord:(NSString *)word andCallBack:(MyCallback)callback{
    483 NSString *path = [NSString stringWithFormat:@"http://mp3.baidu.com/dev/api/?tn=getinfo&ct=0&word=%@&ie=utf-8&format=json",word];
    484 path = [path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    485 NSURL *url = [NSURL URLWithString:path];
    486 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    487 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    488 NSArray *arr = [NSJSONSerialization JSONObjectWithData:data options:0 error:Nil];
    489 if (arr.count==0) {
    490 [TRWebUtils requestMusicsByWord:word andCallBack:callback];
    491 }
    492 NSMutableArray *musics = [TRParser parseMusicInfoByArray:arr];
    493 callback(musics);
    494 }];
    495 }
    496 + (void)requestMusicDetailByMusic:(TRMusicInfo *)music andCallBack:(MyCallback)callback{
    497 NSString *path = [NSString stringWithFormat:@"http://ting.baidu.com/data/music/links?songIds=%@",music.songID];
    498 NSLog(@"%@",path);
    499 NSURL *url = [NSURL URLWithString:path];
    500 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    501 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    502 NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:0 error:Nil];
    503 [TRParser parseMusicDetailByDic:dic andMusic:music];
    504 callback(music);
    505 }];
    506 }
    507 @end
    
    
    
    
    
  • 相关阅读:
    yii2权限控制rbac之rule详细讲解
    yii2权限控制rbac之详细操作步骤
    安装 Autoconf, Automake & Libtool
    Linux查看物理CPU个数、核数、逻辑CPU个数
    Nginx端口占用问题
    Druid加密
    Ubuntu16.04安装Zabbix3.2(快速安装教程)
    飞冰ICE
    BeiDou开源项目
    Arthas开源项目
  • 原文地址:https://www.cnblogs.com/52190112cn/p/5052122.html
Copyright © 2011-2022 走看看