Swift編程實(shí)戰(zhàn)指南--豆瓣電臺(tái)
前段時(shí)間用Swift練手寫了這么一個(gè)demo,后來有朋友希望能出個(gè)教程,于是就搗鼓出這么一個(gè)系列教程,內(nèi)容包括準(zhǔn)備、界面布局、獲取網(wǎng)絡(luò)數(shù)據(jù)、歌曲列表的展現(xiàn)、播放音樂、視圖跳轉(zhuǎn)傳參及回跳、顯示動(dòng)畫、播放進(jìn)度與時(shí)間以及簡單手勢控制暫停播放九個(gè)部分。
Swift實(shí)戰(zhàn)-豆瓣電臺(tái)(一)準(zhǔn)備
我們現(xiàn)在看看我們要做一個(gè)什么樣的東西,觀看地址:http://v.youku.com/v_show/id_XNzI4ODY2Mjky.html
布局
通過上面這張圖我們可以看出整個(gè) demo 有兩個(gè)視圖,視圖一用來播放音樂,視圖二用來選擇頻道。
視圖一
ImageView用來顯示音樂的圖片
TableView用來顯示音樂列表
Progress用來顯示播放進(jìn)度
Label用來顯示播放時(shí)間
Button用來切換視圖
視圖二
Lbale顯示“選擇頻道”
Tableview用來顯示頻道列表
知識(shí)要點(diǎn)
組件:
ImageView
TableView
TableViewCell
Progress
Label
Button
MediaPlayer
知識(shí)點(diǎn):
視圖之間的跳轉(zhuǎn),傳參,回跳
協(xié)議
異步獲取數(shù)據(jù)
Json解析
動(dòng)畫效果
豆瓣API
頻道列表
http://www.douban.com/j/app/radio/channels
歌曲列表
http://douban.fm/j/mine/playlist?channel=0
#p#
Swift實(shí)戰(zhàn)-豆瓣電臺(tái)(二)界面布局
觀看地址:http://v.youku.com/v_show/id_XNzMwMDg4NzAw.html
這節(jié)的內(nèi)容主要是storyboard的操作。
有以下幾個(gè)知識(shí)點(diǎn)
1.TableView的DataSource與Delegate的設(shè)定。我們將其綁定在 ViewController 上,使之遵循 UITableViewDataSource,UITableViewDelegate 協(xié)議來實(shí)現(xiàn)。然后我們實(shí)現(xiàn)了兩個(gè)函數(shù),一個(gè)返回了 TableView 中行數(shù)。也就是 TableView 里面有多少條數(shù)據(jù)。
- func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int{
- return 10
- }
一個(gè)返回了TableView的單元格(cell)實(shí)例,也就是單元格長什么樣
- func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!{
- let cell=UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "douban")
- return cell
- }
2. 單元格的識(shí)別。在 storyboard 中選中 cell。然后設(shè)置 ldentifier 的值來實(shí)現(xiàn)。ldentifier 的值與下列語句中的 reuseIdentifier 的值(”douban”)對(duì)應(yīng)。
- let cell=UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "douban")
3. 從頻道列表中返回主界面如果按照主界面跳轉(zhuǎn)到頻道列表的方式則會(huì)不斷地產(chǎn)生新的主界面。所以用 dismissViewControllerAnimated 函數(shù)來回跳
- self.dismissViewControllerAnimated(true, completion: nil)
本節(jié)高清視頻及項(xiàng)目文件下載地址:http://pan.baidu.com/s/1sjHd5qX
#p#
Swift實(shí)戰(zhàn)-豆瓣電臺(tái)(三)獲取網(wǎng)絡(luò)數(shù)據(jù)
觀看地址:http://v.youku.com/v_show/id_XNzMwMzQxMzky.html
這節(jié)內(nèi)容,我們先說了怎么將storyboard中的組件在類中進(jìn)行綁定。然后寫了一個(gè)類用來獲取網(wǎng)絡(luò)數(shù)據(jù),同時(shí)定義了一個(gè)協(xié)議,在獲取數(shù)據(jù)后進(jìn)行回調(diào)。之后對(duì)json數(shù)據(jù)進(jìn)行解析,轉(zhuǎn)化為一個(gè)字典。
知識(shí)點(diǎn)
異步獲取數(shù)據(jù)
- var nsUrl:NSURL=NSURL(string: url)
- var request:NSURLRequest=NSURLRequest(URL: nsUrl)
- NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!,error: NSError!) -> Void)
NSURL 和 NSURLRequest 都是使用簡單卻難以簡單說明的東西。意會(huì)吧。
NSURLConnection.sendAsynchronousRequest 方法中的 NSOperationQueue.mainQueue() 將獲取數(shù)據(jù)這個(gè)任務(wù)放進(jìn)主隊(duì)列。
completionHandler:完成任務(wù)后函數(shù)調(diào)用。
Json解析
- var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
NSJSONReadingOptions.MutableContainer:設(shè)置返回的對(duì)象是可以隨時(shí)添加新值的Mutable 類型的對(duì)象
協(xié)議
協(xié)議和其他語言中的接口類似,我們?cè)跀?shù)據(jù)獲取類中設(shè)置一個(gè)遵循該協(xié)議的成員,當(dāng)數(shù)據(jù)獲取完畢后,該成員執(zhí)行某個(gè)方法來使用數(shù)據(jù)。我們?nèi)绻挥脜f(xié)議用具體的某個(gè)類也是可以的。但就失去了靈活性。
高清視頻及代碼下載地址:http://pan.baidu.com/s/1sjHd5qX
#p#
Swift實(shí)戰(zhàn)-豆瓣電臺(tái)(四)歌曲列表的展現(xiàn)
觀看地址 : http://v.youku.com/v_show/id_XNzMwNDE0OTA4.html
這節(jié)的主要內(nèi)容是如何利用 cell 展現(xiàn)獲取到的數(shù)據(jù)。
首先申明兩個(gè)數(shù)組來儲(chǔ)存我們獲取到的數(shù)據(jù)
- var tableData:NSArray=NSArray()
- var channelData:NSArray=NSArray()
tableData 是主界面上歌曲列表要用的數(shù)據(jù)。所以在 func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) 這個(gè)方法中要返回tableData的數(shù)量
- func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int{
- return tableData.count
- }
然后我們把tableData中的數(shù)據(jù)填充到主界面的TableView中
- let cell=UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "douban")
- let rowData:NSDictionary=self.tableData[indexPath.row] as NSDictionary
- cell.text=rowData["title"] as String
- cell.detailTextLabel.text=rowData["artist"] as NSString
接著我們?cè)陲@示縮略圖的時(shí)候先給一張默認(rèn)的圖片
- cell.image=UIImage(named:"detail.jpg")
然后我們?nèi)プト【W(wǎng)絡(luò)圖片,同樣,是用異步的方式。為了提高性能,我們對(duì)獲取的圖片做了一個(gè)緩存
- var imageCache = Dictionary<String,UIImage>()
通過圖片的地址來緩存UIImage
- let url=rowData["picture"] as String
- let image=self.imageCache[url] as?UIImage
- if !image?{
- let imgURL:NSURL=NSURL(string:url)
- let request:NSURLRequest=NSURLRequest(URL: imgURL)
- NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response:NSURLResponse!,data:NSData!,error:NSError!)->Void in
- var img=UIImage(data:data)
- cell.image=img
- self.imageCache[url]=img
- })
- }else{
- cell.image=image
- }
本節(jié)高清視頻和代碼下載地址:http://pan.baidu.com/s/1sjHd5qX
#p#
Swift實(shí)戰(zhàn)-豆瓣電臺(tái)(五)播放音樂
觀看地址:http://v.youku.com/v_show/id_XNzMwODM0MzI0.html
在這節(jié)里面,我們簡單學(xué)習(xí)了一下MediaPlayer的使用
引入媒體框架
- import MediaPlayer
聲明一個(gè)媒體播放器
- var audioPlayer:MPMoviePlayerController=MPMoviePlayerController();
播放暫停操作
- self.audioPlayer.stop()
- self.audioPlayer.contentURL=NSURL(string:url)
- self.audioPlayer.play()
本節(jié)高清視頻及源碼下載地址:http://pan.baidu.com/s/1sjHd5qX
#p#
Swift實(shí)戰(zhàn)-豆瓣電臺(tái)(六)視圖跳轉(zhuǎn),傳參及回跳
youku觀看地址:http://v.youku.com/v_show/id_XNzMxMzQ3MDcy.html
要點(diǎn)
在ChannelController里面聲明一個(gè)代理
這個(gè)代理遵循我們自定義的協(xié)議ChannlePrococol。
遵循這個(gè)協(xié)議的主界面類在注入后有一個(gè)回調(diào)方法onChangeChanne將所選擇的頻道返回。
prepareForSegue方法
這個(gè)方法是在準(zhǔn)備跳轉(zhuǎn)的時(shí)候執(zhí)行的。在這里面我們能拿到將要跳轉(zhuǎn)的視圖類segue.destinationViewController,這時(shí)候就能設(shè)置這個(gè)類的代理,并將數(shù)據(jù)傳過去了
高清視頻與代碼下載地址:http://pan.baidu.com/s/1sjHd5qX
#p#
Swift實(shí)戰(zhàn)-豆瓣電臺(tái)(七)顯示動(dòng)畫
youku觀看地址:http://v.youku.com/v_show/id_XNzMxODQzNDIw.html
這是一個(gè)很酷的動(dòng)畫效果。特別是數(shù)據(jù)多的時(shí)候
知識(shí)點(diǎn)
在單元格(Cell)顯示方法中設(shè)置動(dòng)畫
- func tableView(tableView: UITableView!, willDisplayCell cell: UITableViewCell!, forRowAtIndexPath indexPath: NSIndexPath!){
- cell.layer.transform = CATransform3DMakeScale(0.1, 0.1, 1)
- UIView.animateWithDuration(0.25, animations: {
- cell.layer.transform=CATransform3DMakeScale(1, 1, 1)
- })
- }
willDisplayCell 顧名思義。就是在Cell顯示之前。設(shè)置cell的層(layer)的變換(transform)為CATransform3DMakeScale做一個(gè)縮放動(dòng)畫。X,y方向的縮放從0.1到1
高清視頻與代碼下載地址:http://pan.baidu.com/s/1sjHd5qX
#p#
Swift實(shí)戰(zhàn)-豆瓣電臺(tái)(八)播放進(jìn)度與時(shí)間
視頻觀看地址:http://www.tudou.com/programs/view/4mEtz8S72k0/?resourceId=399000367_06_02_99
這節(jié)主要內(nèi)容是 NSTimer,UIProgressView,MPMoviePlayerController 類的使用
NSTimer
實(shí)例化:
- timer=NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: "onUpdate", userInfo: nil, repeats: true)// 實(shí)例化后即啟動(dòng)定時(shí)器,0.4秒后開始第一次觸發(fā)
0.4 是間隔時(shí)間;target 是發(fā)送對(duì)象;selector 是觸發(fā)的方法;userInfo 此參數(shù)可以為 nil,當(dāng)定時(shí)器失效時(shí),由你指定的對(duì)象保留和釋放該定時(shí)器;repeats 是否重復(fù)。
立即觸發(fā)
- fire()
停止
- invalidate()
UIProgressView
設(shè)置進(jìn)度條進(jìn)度
- progressView.progress=0.0
帶動(dòng)畫
- progressView.setProgress(p, animated: true)
MPMoviePlayerController
audioPlayer.currentPlaybackTime 已經(jīng)播放的時(shí)間(秒)
audioPlayer.duration 總時(shí)間(秒)
秒鐘分鐘算法
總時(shí)間除以60的余數(shù)就是秒鐘
總時(shí)間除以60的商就是分鐘
因?yàn)槲覀兊恼宫F(xiàn)形式是00:00
所以當(dāng)數(shù)字小于10的時(shí)候進(jìn)行字符串拼接補(bǔ)0例如01,02
本節(jié)高清視頻和代碼下載地址:http://pan.baidu.com/s/1sjHd5qX
#p#
Swift實(shí)戰(zhàn)-豆瓣電臺(tái)(九)簡單手勢控制暫停播放
全屏清晰觀看地址:http://www.tudou.com/programs/view/tANnovvxR8U/
這節(jié)我們主要講 UITapGestureRecognizer 和 MPMoviePlayerController
知識(shí)點(diǎn)
UITapGestureRecognizer
關(guān)聯(lián)storyboard上的UITapGestureRecognizer
- @IBOutlet var tap:UITapGestureRecognizer=nil //注意要設(shè)置為nil
增加手勢識(shí)別
- addGestureRecognizer(tap)
移除手勢識(shí)別
- removeGestureRecognizer(tap)
關(guān)聯(lián)Action
- @IBAction func onTap(recognizer: UITapGestureRecognizer)
通過 recognizer.view 可以判斷點(diǎn)擊了哪個(gè)組件
- @IBAction func onTap(recognizer: UITapGestureRecognizer){
- if recognizer.view==btnPlay {
- btnPlay.hidden=true
- audioPlayer.play()
- btnPlay.removeGestureRecognizer(tap)
- iv.addGestureRecognizer(tap)
- }else if recognizer.view==iv {
- btnPlay.hidden=false
- audioPlayer.pause()
- btnPlay.addGestureRecognizer(tap)
- iv.removeGestureRecognizer(tap)
- }
- }
MPMoviePlayerController
播放
- play()
暫停
- pause()
本節(jié)高清視頻和代碼下載地址:http://pan.baidu.com/s/1sjHd5qX
原帖地址:http://www.cnblogs.com/sandal1980/p/3812715.html 作者:sandal1980(博客)