Swift实战-QQ在线音乐(第二版)

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

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

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

一、项目准备:

百度音乐国语歌曲列表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 > 2{
                    var s1:NSString = strArr[1].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[2].description.componentsSeparatedByString("]]") as NSArray

                    s1 = s1.stringByReplacingOccurrencesOfString(lastS, withString:s2Arr[0] 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==22000) {
                let resultData:NSArray = result["songlist"] as NSArray
                let list:NSMutableArray = NSMutableArray()

                for(var index:Int=0;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[0] 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 < 2 ){
        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>0){
            var dic:NSDictionary = NSDictionary()
            var startrange:NSRange = item.rangeOfString("[")
            var stoprange:NSRange = item.rangeOfString("]")
            if stoprange.length == 0{
                //歌词没时间
                var songLrc:SongLrc = SongLrc()
                songLrc.total=NSNumber(int: -1)//开始显示的秒数
                songLrc.time=""//开始显示时间
                songLrc.text=item//显示的歌词
                result.addObject(songLrc)

            }else{
                var content:NSString = item.substringWithRange(NSMakeRange(startrange.location+1, stoprange.location-startrange.location-1))
                //歌词有时间
                if (content.length == 8) {
                    var minute:NSString = content.substringWithRange(NSMakeRange(0, 2))
                    var second:NSString = content.substringWithRange(NSMakeRange(3, 2))
                    var mm:NSString = content.substringWithRange(NSMakeRange(6, 2))
                    var time:NSString = NSString(format: "%@:%@.%@", minute,second,mm)
                    var total:NSNumber = NSNumber(integer: minute.integerValue * 60 + second.integerValue)
                    var lyric:NSString = item.substringFromIndex(10)

                    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>0){
            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/8565487

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

时间: 2024-12-21 11:36:05

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

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

1.打开项目QQMusic,然后点菜单:“File-New-Target”添加appleWatch扩展项 2.选择Swift语言,把Include Notification Scene前的勾去掉 (项目暂时不需要做ios端的通知) 3.在 WatchKit Extension的Compile Sources 中添加QQMusic项目的需要使用的类文件 4.在QQMusic WatchKit Extension包的Images.xcassets里添加资源图片 并且在QQMusic WatchKit

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

//一.*项目准备 1.QQ音乐App 界面素材:(我使用PP助手,将QQ音乐App备份,解压ipa文件 即可得到里面的图片素材) 2.豆瓣电台接口:"http://douban.fm/j/mine/playlist?channel=1" //二.*界面布局使用Xcode新建一个Single View Application项目,选择Swift语言. 导入素材图片.在默认的ViewController视图进行以下布局. 界面控件不多,如图将几个关键控件布局就可以了. //三.*背景模糊

零基础Swift实战开发从入门到精通(4大项目实战、酷跑熊猫、百度音乐、足球游戏等)

第一部分:Swift基础语法 第1节:变量 第2节:常量 第3节:使用PlayRound编写Swift程序 第4节:类型检查与推断 第5节:类型别名 第6节:计算器 第二部分:字符和字符串 第1节:字符(Characters) 第2节:字符串-定义 第三部分:数据类型(DataType) 第1节:整型(int.Uint) 第2节:浮点数 第3节:Bool 第四部分:数据类型转换 第1节字符串转换数字类型 第2节数字类型转换字符串 第3节:数字类型之间转换 更多............ 项目实战一

亿级流量电商详情页系统实战-缓存架构+高可用服务架构+微服务架构第二版视频教程

14套java精品高级架构课,缓存架构,深入Jvm虚拟机,全文检索Elasticsearch,Dubbo分布式Restful 服务,并发原理编程,SpringBoot,SpringCloud,RocketMQ中间件,Mysql分布式集群,服务架构,运 维架构视频教程 14套精品课程介绍: 1.14套精 品是最新整理的课程,都是当下最火的技术,最火的课程,也是全网课程的精品: 2.14套资 源包含:全套完整高清视频.完整源码.配套文档: 3.知识也 是需要投资的,有投入才会有产出(保证投入产出比是

junit实战第二版(总结1)

背景 最近就在看junit实战第二版,主要是基于junit4,但是现实中我们有些是基于junit3,如何平稳升级呢? junit3实现方式 测试类必须继承于TestCase类,并且测试方法必须已test开头 junit4实现 直接方法名加上@Test注解即可 注意事项 junit 4.8版本以下只需下载junit的包即可,如果junit4.8以上则还需下载hamcrest-core-1.1.jar,不然会报如下错误java.lang.NoClassDefFoundError: org/hamcr

亿级流量电商详情页系统实战(第二版)

来源:B站  亿级流量电商详情页系统实战(第二版) 电商网站详情页架构: P3:架构1:页面静态化架构:  小电商,静态页面少 Velocity/FreeMarker/Thymeleaf模板 模板+数据 =>最终的页面 如果模板或数据有变更,则需要重新渲染生成页面html->推送nginx P4:大型网站详情页架构 P5: 支撑高可用.高可靠.备份恢复Redis重要性 商品详情页的缓存架构: redis架构: 1)高并发.高可用:海量数据,备份,随时可以恢复,缓存架构如果支撑这些, 首先,Re

Unity网络游戏实战(含第一版和第二版)

目录 按 pdf 第二版配套资源 第一版配套资源 更多坦克大战代码 按 本文主要分享了: Unity网络游戏实战(含第一版和第二版)(罗培羽 著) Unity3D游戏开发(宣雨松著) pdf https://sn9.us/dir/13403389-36671301-a6290f 第二版配套资源 Github: https://luopeiyu.github.io/unity_net_book/ 百度网盘: https://pan.baidu.com/s/1XhYKHJYjWTtGAqMb3uBY

七夜在线音乐台开发 第二弹 (原创)

上一篇我讲了一下七夜在线音乐平台的服务器与域名,也就是设施部分.今天我将大体上的设计思路,技术要点,和大家分享一下. 项目需求:我的目标是设计一个在线音乐平台,大家可以随时点播自己喜欢的歌曲,支持多样化检索,并且根据个人喜好,进行推荐.同时用户可以自定义歌单,支持收藏等功能.提供移动端API接口,可以供app开发使用. 项目框架:我将通过一张图的形式,展示整体的设计方案.(有点简略了,仅仅是给大家看一下,大牛勿喷). 整体框架基本上就是上图所示,接下来咱们根据图中的模块依次讲解所需要的技术要点.

零基础Swift实战开发视频教程_从入门到精通

零基础Swift实战开发从入门到精通(4大项目实战.酷跑熊猫.百度音乐.足球游戏等)适合人群:初级课时数量:50课时更新程度:86%用到技术:Swift涉及项目:酷跑熊猫.百度音乐.足球游戏咨询qq:1840215592零基础Swift实战开发视频教程采用基础+项目的方式进行讲解,通过基础的学习,可以完全掌握Swift基本语法应用,并结合4个项目进行开发,学员能在最短的时间内掌握开发的各项技能. 零基础Swift实战开发从入门到精通详细查看:http://www.ibeifeng.com/goo