標籤:
本文主要分享下樓主在學習Swift編程過程中,對GitHub上的一個開源App Swift Music的研究心得。
項目地址:https://github.com/xujiyao123/SwiftMusic
一、項目簡介
本項目主要實現了歌曲關鍵字查詢歌曲,通過使用
http://h5.kaolafm.com/v3api/api/search?words=\(searchStr)&pageSize=30&pageNum=\(page)&searchType=0&_=1419749689828
http://v3.kaolafm.com/api/play/\(musicId)
這兩個API擷取歌曲詳細資料並進行播放。並通過內建URL訪問並播放指定視頻內容。
二、項目結構分析
樓主之所以選擇分析研究這個項目是因為在學習過程中發現這個項目是一個比較典型的MVC模型,並且所有View部分都是通過代碼實現的而非storyboard,具有一定的學習價值。接下來,本文將按照Model、View、Control,三個部分詳細分析這個項目是如何通過MVC模型來實現查詢歌曲、擷取歌曲、播放歌曲及視頻功能的。
1、 Model(模型)
在Model部分中,作者一共提供了4個檔案。
videos.plist是一個存有所能播放的視頻資料的plist檔案。
在WebImageCategory.swift中,作者拓展了UIIMageView這個class,加入了一個通過URL擷取圖片並載入的方法 setWebImageWithUrlStr(urlStr:String?) -> Void。
在MusicModel.swift中,作者定義了兩個class,分別是:MusicModel和MusicPlayModel。
MusicModel類是用於建立關鍵字搜尋到的歌曲的對象。其中包含了歌曲的5個屬性,並定義了一個類方法loadMusicListDataWithClouse(searchStr:String ,page:Int , clouse:(data:NSMutableArray , haveNext:Int) -> Void) -> Void 通過傳入歌曲關鍵字及搜尋網頁數來擷取歌曲的詳細資料分別建立MusicModel對象並將其裝入一個NSMutableArray中,將所得NSMutableArray傳給方法參數clouse以便進行下一步操作。通過引入方法參數clouse(clousure),作者很巧妙的將資料讀取並進行封裝與對資料之後的操作進行了分離。
MusicPlayModel類則是用於建立通過musicID擷取到的歌曲的對象。其中包含了title,pic,mp3Url三個屬性,並定義類方法loadMusicDataWithClouse(musicID:String ,clouse:(data:NSMutableArray) -> Void) ->Void 通過傳入的musicID,擷取歌曲資訊並建立MusicPlayModel對象並將去裝入NSMutableArray傳遞給方法參數clouse(clousure)以便進行下一步操作。
在VideoModel.swift中,作者定義了一個VideoModel類,也是運用了痛MusicModel類似的手段對視頻資訊資料進行處理並傳遞給clouse。與MusicModel不同的是,在loadVideoDataWithClouse(clouse:(dataArr:NSMutableArray) -> Void) -> Void 中作者通過dispatch_async添加一個非同步任務來處理videos.plist裡的視頻資料。
通過對Model中的4個檔案的分析,不難發現,作者在Model部分定義了資料的模型並通過閉包(clousure)的方式接受後續對資料的操作,以達到將Model與其餘部分分離的目的。由此可見,使用方法參數(閉包clousure)是一個實現MVC很好的辦法。
2、View(視圖)
View部分一共包含了2個檔案。
在XUTableViewCell.swift檔案中作者建立了UITableViewCell並定義了其顯示內容及將VideoModel與MusicModel對象填充入Cell的方法。
在MusicPlayerManager.swift中首先定義了協議MusicPlayDelegate,其中包含了4個方法。在MusicPlayManager類中,定義了協議代理delegate,player: AVPlayer! 及var timer:NSTimer!。通過類變數shared獲得一個MusicPlayerManager()。方法playWithModel(model:MusicPlayModel) 用於播放音樂並使用timer每隔1s出發playing方法。playing() 方法用於判斷播放是否結束,並使用代理調用協議方法playManager(manager:MusicPlayerManager ,BeginToPlayProgress progress:Double) 或 playManagerplayIsEnd(manager:MusicPlayerManager) 並將自身作為參數傳遞給協議方法。pause() 與 goon() 分別是控制player暫停與播放,並將自身作為參數用代理調用相關協議方法。changeValueWithProgress(value:Float64) ->Void 通過參數的傳入來控制player的播放進度。
作者主要在View部分定義了UITableViewCell及MusicPlayerManager並通過使用代理協議的方法,將player本身與其餘部分程式進行了分離。在MVC模型中,使用代理來傳遞值及調用協議方法也是一個很好的辦法。
3、 Controller
在Controller中,作者給出了4個檔案分別對應了本項目中的4個介面。
RootViewController.swift對應的是項目的主菜單。RootViewController.swift中,設定了頁面的背景顏色,定義並執行個體了UINavigationController()及兩個UIButton(),並為兩個UIButton定義了觸發方法用於跳轉頁面至按鈕分別對應的音樂和電影介面。
RootViewController.swift對應的是視頻介面。這之中定義並執行個體了UITableViewController,通過調用VideoModel.loadVideoDataWithClouse(clouse:(dataArr:NSMutableArray) -> Void) -> Void方法擷取視頻資料並通過方法drawCellWithModel(model:VideoModel) ->Void將資料載入cell並填充如UITableViewController。同時定義了tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) 用於實現播放視頻的功能。
MusicListViewController.swift對應著音樂搜尋介面,同視頻介面相似的定義了UITableViewController並調用cell.drawMusicWithModel(model:MusicModel) ->Void進行填充。與視頻介面不同的是,在音樂搜尋介面中作者定義並執行個體了textFild() 用於輸入搜尋索引鍵,並定義loadData(page:Int?) ->Void 方法調用MusicModel.loadMusicListDataWithClouse(searchStr:String ,page:Int , clouse:(data:NSMutableArray , haveNext:Int) -> Void) -> Void 擷取音樂列表。同時作者還定義了select cell方法用於跳轉至音樂播放介面。調用ZLSwifthRefresh 中方法實現列表下拉重新整理的功能。
在MusicViewController.swift中作者執行個體了兩個UIButton用於播放和暫停,一個UIImage用於顯示歌曲圖片並對UIImage進行了圓角和旋轉處理(旋轉動畫+NSTimer觸發器),一個UISlider()用於顯示及控制播放進度。通過使用MusicPlayModel.loadMusicDataWithClouse(musicID:String ,clouse:(data:NSMutableArray) -> Void) ->Void 方法擷取播放歌曲的資料及資訊。使用MusicPlayerManager.shared屬性獲得MusicPlayerManager(),調用MusicPlayerManager()中的方法達到控制播放器播放暫停效果,並獲得協議代理,同時實現代理中的4個方法。
作者在Controller的4個檔案中分別將4個頁面中所包含的各個控制器進行了定義及執行個體。通過不同的指令調用Model中的方法獲得資料,並將資料傳遞給View中的Cell和Player進行顯示及播放。
三、項目音樂部分運行流程圖
四、項目可改進部分
1、項目在URL通訊部分中還在使用NSURLConnection而並未使用功能更加完善的NSURLSession。
2、項目UI及功能較為簡單。
3、雖然定義了MusicPlayerDelegate協議,但在實際實現過程中並未賦予其實用功能。View與Controller間互動也是通過傳遞MusicPlayerManager()來完成的。
五、總結
本項目雖然在功能上較為簡單,但是在程式設計的結構上很好的遵循MVC模型,並通過clousure,代理協議,對象傳遞等方式來達成Model、View和Controller三者之間的互動。這是值得學習的。作者完全使用代碼對介面進行設計,也是值得借鑒的,畢竟有的時候用代碼設計介面比storyboard會來的更為方便。
(IOS)Swift Music 程式分析