Swift版音乐播放器(简化版),swift音乐播放器
生活随笔
收集整理的這篇文章主要介紹了
Swift版音乐播放器(简化版),swift音乐播放器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
這幾天閑著也是閑著,學習一下Swift的,于是到開源社區Download了個OC版的音樂播放器,練練手,在這里發揚開源精神,
希望對大家有幫助!
這個DEMO里,使用到了
AudioPlayer(對音頻封裝的庫)
FreeStreamer(老外寫的音頻高效處理庫)
LKDBHelper(將數據模型直接寫到數據庫中的庫)
AFNetworking (網絡庫)
SDWebImage (圖片獲取庫)
另外,我也把OC版的ProgressHUD轉成了Swift版本的HYBProgressHUD,希望對大家有用啊!
目前只實現了這幾個簡單的功能,希望有時間且愛研究的同學,追加更多的功能再開源出來哦!
下面我說一下封裝的網絡請求類:
import Foundation/// 請求成功與失敗的回調 typealias requestSuccessCloser = (responseObject: AnyObject?) ->Void typealias failCloser = (error: NSError?) ->Void/// /// 描述:網絡請求基礎類,所有GET請求方式都是以GET開頭的類方法,POST請求方式會以POST開頭命名類方法 /// /// 作者:huangyibiao class HYBBaseRequest: NSObject {struct BaseURL {static var baseURL: String = kServerBase}////// 描述:解析JSON數據////// 參數:jsonObject 網絡請求獲取下來數據////// 返回:如果解析成功,返回字典,否則返回nilclass func parseJSON(#jsonObject: AnyObject?) ->NSDictionary? {if let result = jsonObject as? NSDictionary {return result}return nil}////// 描述: GET請求方式////// 參數: serverPath --請求路徑,不包含基礎路徑/// success --請求成功時的回調閉包/// fail --請求失敗時的回調閉包////// 返回: AFHTTPRequestOperation類型對象,外部可以通過引用此對象實例,在需要取消請求時,調用cancel()方法class func GETRequest(serverPath: String, success: requestSuccessCloser, fail: failCloser) ->AFHTTPRequestOperation {var op = manager().GET(serverPath, parameters: nil, success: { (op, responseObject) -> Void insuccess(responseObject: responseObject)}, failure: { (op, error) -> Void infail(error: error)})return op}class func downloadFile(serverPath: String, success: requestSuccessCloser, fail: failCloser) ->AFHTTPRequestOperation {var op = AFHTTPRequestOperation(request: NSURLRequest(URL: NSURL(string: String(format: "%@%@", kServeBase1, serverPath))))op.setCompletionBlockWithSuccess({ (requestOp, responseObject) -> Void insuccess(responseObject: responseObject)}, failure: { (requestOP, error) -> Void infail(error: error)})op.start()return op}////// 私有方法區///private class func manager() ->AFHTTPRequestOperationManager {var manager = AFHTTPRequestOperationManager(baseURL: NSURL(string: BaseURL.baseURL))manager.requestSerializer.setValue("application/json", forHTTPHeaderField: "Accept")manager.requestSerializer.setValue("application/json", forHTTPHeaderField: "content-type")manager.requestSerializer.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Accept")manager.requestSerializer.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")// 設置響應頭支持的格式manager.responseSerializer.acceptableContentTypes = NSSet(array: ["application/json", "application/javascript", "application/lrc", "application/x-www-form-urlencoded"])return manager} }
因為資源類型不同,所以要在請求頭添加支持的格式才能訪問到資源哦。
下面是封裝歌詞顯示的UI,這里沒有細化對時間的把握,只是粗略實現功能,有時間的同學可以對播放進度把握得更好!
import Foundation/// /// 描述: 顯示歌詞控件 /// /// 作者: huangyibiao class HYBSongLRCView: UIView {private var scrollView: UIScrollView!private var keyArray = NSMutableArray()private var titleArray = NSMutableArray()private var lineLabelArray = NSMutableArray()private var currentPlayingLineTime: float_t = 0.0////// 重寫父類的方法///override init(frame: CGRect) {super.init(frame: frame)self.scrollView = UIScrollView(frame: CGRectMake(0, 10, self.width(), self.height() - 20))// 暫時關閉可交互功能self.scrollView.userInteractionEnabled = falseself.addSubview(self.scrollView)}required init(coder aDecoder: NSCoder) {fatalError("init(coder:) has not been implemented")}////// public方法區///////// 描述:解析歌詞////// 參數:lrcPath LRC歌詞的路徑func parseSong(lrcPath: String) {self.keyArray.removeAllObjects()self.titleArray.removeAllObjects()var content = NSString(contentsOfFile: lrcPath, encoding: NSUTF8StringEncoding, error: nil)var array = content.componentsSeparatedByString("\n")// 解析每一行for line in array {if let lrcLine = line as? NSString {if lrcLine.length != 0 {self.parseLRCLine(lrcLine)}}}self.bubbleSortLrcLines(self.keyArray)self.scrollView.contentOffset = CGPointZeroself.scrollView.contentSize = CGSizeMake(scrollView.width(), CGFloat(keyArray.count * 25))self.configureLRCLineLabels()}////// 描述:移除顯示歌詞的標簽func removeAllSubviewsInScrollView() {for subview in self.scrollView.subviews {subview.removeFromSuperview()}self.lineLabelArray.removeAllObjects()}////// 描述:移除之前的歌詞數據func clearLRCContents() {self.keyArray.removeAllObjects()self.titleArray.removeAllObjects()}////// 描述:指定歌詞播放的時間,會根據時間滾動到對應的歌詞行////// 參數:time 歌詞行播放的時間func moveToLRCLine(#time: NSString) {if self.keyArray.count != 0 {var currentTimeValue = self.timeToFloat(time)var index = 0var hasFound = falsefor index = 0; index < self.keyArray.count; index++ {if let lrcTime = self.keyArray[index] as? NSString {var tmpTimeValue = self.timeToFloat(lrcTime)if fabs(tmpTimeValue - currentTimeValue) <= fabs(0.000000001) {hasFound = truecurrentPlayingLineTime = tmpTimeValuebreak}}}if hasFound || (!hasFound && currentPlayingLineTime < currentTimeValue) {if index < self.lineLabelArray.count {if let label = self.lineLabelArray[index] as? UILabel {updateCurrentTimeLRC(label)self.scrollView.setContentOffset(CGPointMake(0.0, 25.0 * CGFloat(index)),animated: true)}}}}}////// private方法區///////// 描述:解析歌詞行////// 參數:lrcLine 該行歌詞private func parseLRCLine(lrcLine: NSString) {if lrcLine.length == 0 {return}var array = lrcLine.componentsSeparatedByString("\n")for var i = 0; i < array.count; i++ {var tempString = array[i] as NSStringvar lineArray = tempString.componentsSeparatedByString("]")for var j = 0; j < lineArray.count - 1; j++ {var line = lineArray[j] as NSStringif line.length > 8 {var str1 = tempString.substringWithRange(NSMakeRange(3, 1))var str2 = tempString.substringWithRange(NSMakeRange(6, 1))if str1 == ":" && str2 == "." {var lrc = lineArray.last as NSStringvar time = lineArray[j].substringWithRange(NSMakeRange(1, 8)) as NSString// 時間作為KEYself.keyArray.addObject(time.substringToIndex(5))// 歌詞會為值self.titleArray.addObject(lrc)}}}}}////// 描述:對所有歌詞行進行冒泡排序////// 參數:array 要進行冒泡排序的數組private func bubbleSortLrcLines(array: NSMutableArray) {for var i = 0; i < array.count; i++ {var firstValue = self.timeToFloat(array[i] as NSString)for var j = i + 1; j < array.count; j++ {var secondValue = self.timeToFloat(self.keyArray[j] as NSString)if firstValue > secondValue {array.exchangeObjectAtIndex(i, withObjectAtIndex: j)self.titleArray.exchangeObjectAtIndex(i, withObjectAtIndex: j)}}}}////// 描述:把時間字符串轉換成浮點值////// 參數:time 時間字符串,格式為:"05:11"private func timeToFloat(time: NSString) ->float_t {var array = time.componentsSeparatedByString(":")var result: NSString = "\(array[0])"if array.count >= 2 {result = "\(array[0]).\(array[1])"}return result.floatValue}////// 描述:創建顯示歌詞的標簽private func configureLRCLineLabels() {self.removeAllSubviewsInScrollView()for var i = 0; i < titleArray.count; i++ {var title = titleArray[i] as Stringvar label = UIMaker.label(CGRectMake(0.0,25.0 * CGFloat(i) + scrollView.height() / 2.0,scrollView.width(),25.0),title: title)label.textColor = UIColor.lightGrayColor()label.font = UIFont.systemFontOfSize(14.0)scrollView.addSubview(label)lineLabelArray.addObject(label)}}////// 描述:更新當前顯示的歌詞private func updateCurrentTimeLRC(currentLabel: UILabel) {for label in self.lineLabelArray {if let item = label as? UILabel {if item == currentLabel {item.textColor = kNavColoritem.font = UIFont.boldSystemFontOfSize(16.0)} else {item.textColor = UIColor.lightGrayColor()item.font = UIFont.systemFontOfSize(14.0)}}}} }Swift版的HYBProgressHUD控件,調用方式是非常簡單的,使用的都是公開的類方法調用方式:
import Foundation import UIKit/// /// @brief 樣式 enum HYBProgressHUDStyle {case BlackHUDStyle /// 黑色風格case WhiteHUDStyle /// 白色風格 }/// /// @brief 定制顯示通知的視圖HUD /// @author huangyibiao class HYBProgressHUD: UIView {var hud: UIToolbar?var spinner: UIActivityIndicatorView?var imageView: UIImageView?var titleLabel: UILabel?////// private 屬性///private let statusFont = UIFont.boldSystemFontOfSize(16.0)private var statusColor: UIColor!private var spinnerColor: UIColor!private var bgColor: UIColor!private var successImage: UIImage!private var errorImage: UIImage!////// @brief 單例方法,只允許內部調用private class func sharedInstance() ->HYBProgressHUD {struct Instance {static var onceToken: dispatch_once_t = 0static var instance: HYBProgressHUD?}dispatch_once(&Instance.onceToken, { () -> Void inInstance.instance = HYBProgressHUD(frame: UIScreen.mainScreen().bounds)Instance.instance?.setStyle(HYBProgressHUDStyle.WhiteHUDStyle)})return Instance.instance!}override init(frame: CGRect) {super.init(frame: frame)hud = nilspinner = nilimageView = niltitleLabel = nilself.alpha = 0.0}required init(coder aDecoder: NSCoder) {fatalError("init(coder:) has not been implemented")}////// 公開方法////// 顯示信息class func show(status: String) {sharedInstance().configureHUD(status, image: nil, isSpin: true, isHide: false)}/// 顯示成功信息class func showSuccess(status: String) {sharedInstance().configureHUD(status, image: sharedInstance().successImage, isSpin: false, isHide: true)}/// 顯示出錯信息class func showError(status: String) {sharedInstance().configureHUD(status, image: sharedInstance().errorImage, isSpin: false, isHide: true)}/// 隱藏class func dismiss() {sharedInstance().hideHUD()}////// 私有方法///////// @brief 創建并配置HUDprivate func configureHUD(status: String?, image: UIImage?, isSpin: Bool, isHide: Bool) {configureProgressHUD()/// 標題if status == nil {titleLabel!.hidden = true} else {titleLabel!.text = status!titleLabel!.hidden = false}// 圖片if image == nil {imageView?.hidden = true} else {imageView?.hidden = falseimageView?.image = image}// spinif isSpin {spinner?.startAnimating()} else {spinner?.stopAnimating()}rotate(nil)addjustSize()showHUD()if isHide {NSThread.detachNewThreadSelector("hideWhenTimeout", toTarget: self, withObject: nil)}}////// @brief 設置風格樣式,默認使用的是黑色的風格,如果需要改成白色的風格,請在內部修改樣式private func setStyle(style: HYBProgressHUDStyle) {switch style {case .BlackHUDStyle:statusColor = UIColor.whiteColor()spinnerColor = UIColor.whiteColor()bgColor = UIColor(white: 0, alpha: 0.8)successImage = UIImage(named: "ProgressHUD.bundle/success-white.png")errorImage = UIImage(named: "ProgressHUD.bundle/error-white.png")breakcase .WhiteHUDStyle:statusColor = UIColor.whiteColor()spinnerColor = UIColor.whiteColor()bgColor = UIColor(red: 192.0 / 255.0, green: 37.0 / 255.0, blue: 62.0 / 255.0, alpha: 1.0)successImage = UIImage(named: "ProgressHUD.bundle/success-white.png")errorImage = UIImage(named: "ProgressHUD.bundle/error-white.png")breakdefault:break}}////// @brief 獲取窗口windowprivate func getWindow() ->UIWindow {if let delegate: UIApplicationDelegate = UIApplication.sharedApplication().delegate {if let window = delegate.window {return window!}}return UIApplication.sharedApplication().keyWindow}////// @brief 創建HUDprivate func configureProgressHUD() {if hud == nil {hud = UIToolbar(frame: CGRectZero)hud?.barTintColor = bgColorhud?.translucent = truehud?.layer.cornerRadius = 10hud?.layer.masksToBounds = true/// 監聽設置方向變化NSNotificationCenter.defaultCenter().addObserver(self,selector: "rotate:",name: UIDeviceOrientationDidChangeNotification,object: nil)}if hud!.superview == nil {getWindow().addSubview(hud!)}if spinner == nil {spinner = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)spinner!.color = spinnerColorspinner!.hidesWhenStopped = true}if spinner!.superview == nil {hud!.addSubview(spinner!)}if imageView == nil {imageView = UIImageView(frame: CGRectMake(0, 0, 28, 28))}if imageView!.superview == nil {hud!.addSubview(imageView!)}if titleLabel == nil {titleLabel = UILabel(frame: CGRectZero)titleLabel?.backgroundColor = UIColor.clearColor()titleLabel?.font = statusFonttitleLabel?.textColor = statusColortitleLabel?.baselineAdjustment = UIBaselineAdjustment.AlignCenterstitleLabel?.numberOfLines = 0titleLabel?.textAlignment = NSTextAlignment.CentertitleLabel?.adjustsFontSizeToFitWidth = false}if titleLabel!.superview == nil {hud!.addSubview(titleLabel!)}}////// @brief 釋放資源private func destroyProgressHUD() {NSNotificationCenter.defaultCenter().removeObserver(self, name: UIDeviceOrientationDidChangeNotification, object: nil)titleLabel?.removeFromSuperview()titleLabel = nilspinner?.removeFromSuperview()spinner = nilimageView?.removeFromSuperview()imageView = nilhud?.removeFromSuperview()hud = nil}////// @brief 設置方向變化通知處理func rotate(sender: NSNotification?) {var rotation: CGFloat = 0.0switch UIApplication.sharedApplication().statusBarOrientation {case UIInterfaceOrientation.Portrait:rotation = 0.0breakcase .PortraitUpsideDown:rotation = CGFloat(M_PI)breakcase .LandscapeLeft:rotation = -CGFloat(M_PI_2)breakcase .LandscapeRight:rotation = CGFloat(M_PI_2)breakdefault:break}hud?.transform = CGAffineTransformMakeRotation(rotation)}////// @brief 調整大小private func addjustSize() {var rect = CGRectZerovar width: CGFloat = 100.0var height: CGFloat = 100.0/// 計算文本大小if titleLabel!.text != nil {var style = NSMutableParagraphStyle()style.lineBreakMode = NSLineBreakMode.ByCharWrappingvar attributes = [NSFontAttributeName: statusFont, NSParagraphStyleAttributeName: style.copy()]var option = NSStringDrawingOptions.UsesLineFragmentOriginvar text: NSString = NSString(CString: titleLabel!.text!.cStringUsingEncoding(NSUTF8StringEncoding)!,encoding: NSUTF8StringEncoding)rect = text.boundingRectWithSize(CGSizeMake(160, 260), options: option, attributes: attributes, context: nil)rect.origin.x = 12rect.origin.y = 66width = rect.size.width + 24height = rect.size.height + 80if width < 100 {width = 100rect.origin.x = 0rect.size.width = 100}}hud!.center = CGPointMake(kScreenWidth / 2, kScreenHeight / 2)hud!.bounds = CGRectMake(0, 0, width, height)var h = titleLabel!.text == nil ? height / 2 : 36imageView!.center = CGPointMake(width / 2, h)spinner!.center = CGPointMake(width / 2, h)titleLabel!.frame = rect}////// @brief 顯示private func showHUD() {if self.alpha == 0.0 {self.alpha = 1.0hud!.alpha = 0.0self.hud!.transform = CGAffineTransformScale(self.hud!.transform, 1.4, 1.4)UIView.animateKeyframesWithDuration(0.15,delay: 0.0,options: UIViewKeyframeAnimationOptions.AllowUserInteraction,animations: { () -> Void inself.hud!.transform = CGAffineTransformScale(self.hud!.transform, 1.0 / 1.4, 1.0 / 1.4)self.hud!.alpha = 1.0}, completion: { (isFinished) -> Void in})}}////// @brief 隱藏private func hideHUD() {if self.alpha == 1.0 {UIView.animateKeyframesWithDuration(0.2,delay: 0.0,options: UIViewKeyframeAnimationOptions.AllowUserInteraction,animations: { () -> Void inself.hud!.transform = CGAffineTransformScale(self.hud!.transform, 0.35, 0.35)self.hud!.alpha = 0.0}, completion: { (isFinished) -> Void inself.destroyProgressHUD()self.alpha = 0.0})}}////// @brief 在指定時間內隱藏func hideWhenTimeout() {autoreleasepool { () -> () invar length = countElements(self.titleLabel!.text!)var sleepTime: NSTimeInterval = NSTimeInterval(length) * 0.04 + 0.5NSThread.sleepForTimeInterval(sleepTime)self.hideHUD()}} }剩下的部分, 就需要有耐心的同學們去研究代碼了,點擊這里可以下載到源代碼
?
最精簡版的音樂播放器
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Swift版音乐播放器(简化版),swift音乐播放器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 运用@media实现网页自适应中的几个关
- 下一篇: fdisk 磁盘分区命令