此版本使用百度音乐接口,原因是豆瓣接口很多歌曲没办法找到歌词。

此版本添加了歌词的显示、上一曲、下一曲的实现、歌曲列表指明当前歌曲。

下面来看一下实现过程》》》

一、项目准备:

百度音乐国语歌曲列表Api接口:

http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.song.getSmartSongList&page_no=1&page_size=50&scene_id=42&item_id=115&version=5.2.1&from=ios&channel=appstore

百度音乐mp3搜索Api接口:

http://box.zhangmen.baidu.com/x?op=12&count=1&title=歌曲名称$$歌唱者$$$$

二、修改实体Song.swift 让其跟百度音乐 列表字段名称一致

import Foundation
class Song: NSObject { var artist_id:NSNumber = 0.0
var language:NSString = ""
var pic_big:NSString = ""
var pic_small:NSString = ""
var country:NSString = ""
var area:NSNumber = 0.0
var publishtime:NSString = ""
var album_no:NSNumber = 0.0
var lrclink:NSString = ""
var versions:NSString = ""
var copy_type:NSNumber = 0.0
var file_duration:NSNumber = 0.0
var hot:NSString = ""
var all_artist_ting_uid:NSNumber = 0.0
var pic_premium:NSString = ""
var pic_huge:NSString = ""
var pic_singer:NSString = ""
var all_rate:NSString = ""
var resource_type:NSNumber = 0.0
var all_artist_id:NSNumber = 0.0
var compose:NSString = ""
var songwriting:NSString = ""
var del_status:NSNumber = 0.0
var has_mv_mobile:NSNumber = 0.0
var song_id:NSNumber = 0.0
var title:NSString = ""
var ting_uid:NSNumber = 0.0
var author:NSString = ""
var album_id:NSNumber = 0.0
var album_title:NSString = ""
var is_first_publish:NSNumber = 0.0
var havehigh:NSNumber = 0.0
var charge:NSNumber = 0.0
var has_mv:NSNumber = 0.0
var learn:NSNumber = 0.0
var song_source:NSString = ""
var piao_id:NSNumber = 0.0
var korean_bb_song:NSNumber = 0.0
var resource_type_ext:NSNumber = 0.0
}

三、使用block 封装请求接口

新建DataProvider.swift文件 代码如下:

import Foundation

class DataProvider:NSObject,HttpProtocol{

    var blockRecive:(NSDictionary) -> () = {param in }
var eHttp:HttpController = HttpController()
override init(){
super.init()
eHttp.delegate=self
} //**
//*获取歌曲列表
//*
func getSongList(reciveBlock:(NSDictionary) -> () = {param in }){
blockRecive=reciveBlock
eHttp.onSearch("http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.song.getSmartSongList&page_no=1&page_size=50&scene_id=42&item_id=115&version=5.2.1&from=ios&channel=appstore")
// } //**
//*获取歌曲mp3信息
//*
func getSongMp3(p:Song,reciveBlock:(NSString) -> () = {param in }){ var url:NSString = "http://box.zhangmen.baidu.com/x?op=12&count=1&title=\(p.title)$$\(p.author)$$$$"
var nsUrl:NSURL=NSURL(string:url.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)!
var request:NSURLRequest=NSURLRequest(URL:nsUrl)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response:NSURLResponse!,data:NSData!,error:NSError!)->Void in
if (data != nil){
var reciveString:NSString = NSString(data: data, encoding: NSUTF8StringEncoding)!
//
var strArr:NSArray = reciveString.componentsSeparatedByString("<![CDATA[") as NSArray
if strArr.count > {
var s1:NSString = strArr[].description
s1 = s1.stringByReplacingOccurrencesOfString("$]]></encode><decode>", withString: "")
var sArr:NSArray = s1.componentsSeparatedByString("/") as NSArray
var lastS:NSString = sArr.lastObject as NSString var s2Arr:NSArray = strArr[].description.componentsSeparatedByString("]]") as NSArray s1 = s1.stringByReplacingOccurrencesOfString(lastS, withString:s2Arr[] as NSString)
NSLog("得到mp3文件地址为:%@", s1); reciveBlock(s1)
}
}
})
}
//**
//*请求网络数据结果
//*
func didRecieveResults(results:NSDictionary){
// NSLog("请求到的数据:%@", results)
blockRecive(results)
}
}

三、修改第一版中调用请求的方法,因为封装到类DataProvider了,只需要从DataProvider上去调用。

  //请求列表数据
provider.getSongList { (results) -> () in
let errorCode:NSInteger=results["error_code"] as NSInteger
let result:NSDictionary=results["result"] as NSDictionary
if (errorCode==) {
let resultData:NSArray = result["songlist"] as NSArray
let list:NSMutableArray = NSMutableArray() for(var index:Int=;index<resultData.count;index++){
var dic:NSDictionary = resultData[index] as NSDictionary
var song:Song=Song()
song.setValuesForKeysWithDictionary(dic as NSDictionary)
list.addObject(song)
}
self.tableData=list
self.setCurrentSong(list[] as Song)
}
}

四、在设置当前歌曲的方法里增加请求mp3文件,和请求lrc歌词的调用

//设置当前播放的音乐
func setCurrentSong(curSong:Song){
currentSong=curSong
currentIndex=tableData.indexOfObject(curSong)
photo.image=getImageWithUrl(currentSong.pic_premium)
backgroundImageView.image=photo.image
titleLabel.text=currentSong.title
artistLabel.text="— \(currentSong.author) —"
playButton.selected=false
playTimeLabel.text="00:00"
lrcLabel.text=""
self.progressSlider.value=0.0
self.rotationAnimation()
self.audioPlayer.stop()
timer?.invalidate()
timer=NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "updateTime", userInfo: nil, repeats: true) getCurrentMp3(curSong)
getCurrentLrc(curSong.lrclink)
}

请求当前的mp3文件

 //获取当前mp3
func getCurrentMp3(song:Song){
provider.getSongMp3(song, reciveBlock: { (results) -> () in
self.audioPlayer.contentURL=NSURL(string: results)
})
}

请求当前的lrc歌词文件

 //获取歌词
func getCurrentLrc(lrclick:NSString){
currentLrcData=parseLyricWithUrl(lrclick)?
}

对歌词文件的解析-存储到NSArray<ShongLrc>变量中

/**
*解析歌词
*/
func parseLyricWithUrl(urlString:NSString)->NSArray?{
if ( urlString.length < ){
return nil
}
var url : NSURL = NSURL(string:urlString)!
var lyc : NSString = NSString(contentsOfURL: url, encoding:NSUTF8StringEncoding, error: nil)!
NSLog("获取到歌词文件内容:%@", lyc)
var result:NSMutableArray = NSMutableArray()
for lStr in lyc.componentsSeparatedByString("\n") {
var item:NSString = lStr as NSString
if(item.length>){
var dic:NSDictionary = NSDictionary()
var startrange:NSRange = item.rangeOfString("[")
var stoprange:NSRange = item.rangeOfString("]")
if stoprange.length == {
//歌词没时间
var songLrc:SongLrc = SongLrc()
songLrc.total=NSNumber(int: -)//开始显示的秒数
songLrc.time=""//开始显示时间
songLrc.text=item//显示的歌词
result.addObject(songLrc) }else{
var content:NSString = item.substringWithRange(NSMakeRange(startrange.location+, stoprange.location-startrange.location-))
//歌词有时间
if (content.length == ) {
var minute:NSString = content.substringWithRange(NSMakeRange(, ))
var second:NSString = content.substringWithRange(NSMakeRange(, ))
var mm:NSString = content.substringWithRange(NSMakeRange(, ))
var time:NSString = NSString(format: "%@:%@.%@", minute,second,mm)
var total:NSNumber = NSNumber(integer: minute.integerValue * + second.integerValue)
var lyric:NSString = item.substringFromIndex() var songLrc:SongLrc = SongLrc()
songLrc.total=total//开始显示的秒数
songLrc.time=time//开始显示时间
songLrc.text=lyric//显示的歌词
result.addObject(songLrc)
}
} }
}
return result
}

五、为上一首、下一首添加事件

 //上一曲
@IBAction func preSongClick(sender: UIButton){
if(currentIndex>){
currentIndex--
}
currentSong=tableData.objectAtIndex(currentIndex) as Song
setCurrentSong(currentSong)
} //下一曲
@IBAction func nextSongClick(sender: UIButton){
if(currentIndex < tableData.count){
currentIndex++
}
currentSong=tableData.objectAtIndex(currentIndex) as Song
setCurrentSong(currentSong)
}

六、在歌曲列表中显示当前播放的歌曲

 //当前行数据
let rowSong:Song=self.tableData[indexPath.row] as Song
//行显示内容
cell.textLabel?.text=rowSong.title
cell.textLabel?.font=UIFont(name: "宋体", size: 14.0)
//如果是当前歌曲显示绿色
if indexPath.row == self.viewContorller.currentIndex{
cell.textLabel?.textColor=UIColor.greenColor()
}else{
cell.textLabel?.textColor=UIColor.whiteColor()
}
cell.detailTextLabel?.text=rowSong.author
cell.detailTextLabel?.font=UIFont(name:"宋体", size: 8.0)

最终效果:

 

源码下载地址:http://download.csdn.net/detail/fangwulongtian/8568535

原文出自:http://www.cnblogs.com/wuxian/p/4397153.html 转载就注明来源

Swift实战-QQ在线音乐(第二版)的更多相关文章

  1. Swift实战-QQ在线音乐(AppleWatch版)

    1.打开项目QQMusic,然后点菜单:“File-New-Target”添加appleWatch扩展项 2.选择Swift语言,把Include Notification Scene前的勾去掉 (项 ...

  2. Swift实战-QQ在线音乐(第一版)

    //一.*项目准备 1.QQ音乐App 界面素材:(我使用PP助手,将QQ音乐App备份,解压ipa文件 即可得到里面的图片素材) 2.豆瓣电台接口:"http://douban.fm/j/ ...

  3. c#多线程编程实战(原书第二版)文摘

    Thread t = new Thread(PrintNumbersWithDelay); t.Start(); t.Join(); 但我们在主程序中调用了t.Join方法,该方法允许我们等待直到线程 ...

  4. 《selenium2 Java 自动化测试实战(第二版)》 更新2016.5.3

    java 版来了!! 本文档在<selenium2 Python 自动化测试实战>的基础上,将代码与实例替换为java ,当然,部分章节有变更.这主要更语言本身的特点有关.集合和java下 ...

  5. javascript版QQ在线聊天挂件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. Docker技术入门与实战 第二版-学习笔记-10-Docker Machine 项目-2-driver

    1>使用的driver 1〉generic 使用带有SSH的现有VM/主机创建机器. 如果你使用的是机器不直接支持的provider,或者希望导入现有主机以允许Docker Machine进行管 ...

  7. Docker技术入门与实战 第二版-学习笔记-8-网络功能network-3-容器访问控制和自定义网桥

    1)容器访问控制 容器的访问控制,主要通过 Linux 上的 iptables防火墙来进行管理和实现. iptables是 Linux 上默认的防火墙软件,在大部分发行版中都自带. 容器访问外部网络 ...

  8. 100个Swift必备Tips(第二版)

    100个Swift必备Tips(第二版) 新年第一天,给大家一本电子书,希望新的一年里,步步高升. GitHub

  9. R语言实战(第二版)-part 1笔记

    说明: 1.本笔记对<R语言实战>一书有选择性的进行记录,仅用于个人的查漏补缺 2.将完全掌握的以及无实战需求的知识点略去 3.代码直接在Rsudio中运行学习 R语言实战(第二版) pa ...

随机推荐

  1. LR调用动态链接库DLL

    什么是动态库? 动态库一般又叫动态链接库(DLL),是Dynamic Link Library 的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库. 动态链接提供了一种方法 ,使进程可以 ...

  2. 大话数据结构(十)java程序——队列

    1.队列的定义 队列(queue):是只允许在一端进行插入操作,而在另一端进行删除操作的线性表. 队列是一种先进先出的线性表,简称FIFO(First out firts in).允许插入的一头是队尾 ...

  3. 大话数据结构(五)(java程序)——顺序存储结构的插入与删除

    获得元素操作 对于线性表的顺序存储结构来说,我们要实现getElement操作,即将线性表的第i个位置元素返回即可 插入操作 插入算法思路: 1.如果插入位置不合理,抛出异常 2.如果插入表的长度大于 ...

  4. Java中常用的内存区域

    在Java中主要存在4块内存空间,这些内存空间的名称及作用如下. 1.  栈内存空间: 保存所有对象名称(更准确的说是保存了引用的堆内存空间的地址). 2.  堆内存空间: 保存每个对象的具体属性内容 ...

  5. Finally 与 return

    网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行?很多人都说不是,当然他们的回答是正确的,经过我试验,至少有两种情况下fina ...

  6. fstream 坑解决办法

    status_t SysWatcher::setWVer() {     fstream myfile;     myfile.open("/data/w_version", io ...

  7. GATT 服务器与客户端角色

    两个设备应用数据的通信是通过协议栈的GATT层实现的.从GATT角度来看,当两个设备建立连接后,他们处于以下两种角色之一: GATT服务器: 它是为GATT客户端提供数据服务的设备 GATT客户端:  ...

  8. 低功耗蓝牙4.0BLE编程-nrf51822开发(2)

    相关下载:http://download.csdn.net/detail/xgbing/9565708 首先看的示例是心率计一个示例程序:<KEIL path> \ARM\Device\N ...

  9. 【Android测试】【第一节】性能——CPU

    ◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/5065083.html 前言 本来打算写完全部的自动化测试之 ...

  10. [LeetCode] Longest Palindromic Substring(manacher algorithm)

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...