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

 


 

posted on 2015-12-16 19:24  A蜗牛为梦想而生A  阅读(308)  评论(0编辑  收藏  举报