swift4.0實現(xiàn)視頻 、屏幕旋轉(zhuǎn)、倍速 、手勢調(diào)節(jié)及鎖屏面板等功能實例
前言
學習swift有段時間了,原來寫過一個基于 swift 3.0 的視頻 ,后來有同學聯(lián)系我說,在音頻鎖屏的情況下,無法用控制面板拖動進度條調(diào)節(jié) 進度,所以又將原來的代碼拿過來重新整理了下也順便更新到了4.0版本。在把原來的代碼拿來的時候發(fā)現(xiàn)原來有好多地方都是錯誤的,原來在 OC 項目里面已經(jīng)寫過一遍關于視頻 的東西所以就按照原來的邏輯寫了 swift 版本,其實里面很多代碼我也是通過查找資料和看文檔拼湊出來的,對于 swift 的語句也是一知半解,希望各位看官多多包涵。
先來看一下實現(xiàn)的效果,一圖勝千言(第一張是 iOS 10系統(tǒng),第二張是 iOS 11系統(tǒng))。
demo下載地址 (本地下載)
工程介紹
簡單說一下工程結(jié)構(gòu),所有關于布局都是在Player文件夾下的MPlayerViewModel文件中,考慮到耦合度的原因,所以將視頻 的所有 UI 布局全部抽離出來,在 器 view 里將會頻繁看到一個叫viewModel的對象,它既 UI 布局也是布局控件的所有者。視頻 的布局是基于SnapKit三方庫來布局了,因為在OC里用慣了Masonry所以工程里依然沿用這個庫。主要代碼是放到MPlayerView這個文件中的,其中還有一個由 OC 寫的DeviceTool文件主要用來做頁面強制旋轉(zhuǎn)用的,強制旋轉(zhuǎn)這一部分我現(xiàn)在還沒有更好的解決辦法只能橋接 OC 里的方法。
初始化 器方法
視頻 界面我用的是一個單例實現(xiàn)的,剛開始不是用單例實現(xiàn),但是為了把代碼拆出來放到各自的功能區(qū)所以用單例實現(xiàn)是最好的方法。由于swift放棄了OC里的dispatch_once實現(xiàn)單例方法,swift3.0以后的單例寫法:
/// 創(chuàng)建 器單例 static let shared = MPlayerView() private override init(frame: CGRect) { super.init(frame: frame) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
在swift3.0之后重寫init方法必須實現(xiàn)required init方法,這么做也是為了安全,因為在OC里init方法并不能保證子類完成初始化,增加required“這是由初始化方法的完備性需求所決定的,以保證類型的安全。在創(chuàng)建視頻 視圖有兩種創(chuàng)建方式:1.用單利創(chuàng)建。2.init 初始化 ,這兩種方法都可以達到視頻 的效果。
1.單利初始化
self.playerView = MPlayerView.shared.initWithFrame(frame: self.view.frame, videoUrl: videoUrl, type: "VIDEO")
2.init 初始化
self.playerView = MPlayerView().initWithFrame(frame: CGRect.init(x: 0, y: 0, width: Screen_width, height: Screen_width * 9/16), videoUrl: videoUrl, type: "VIDEO")
手勢滑動及注意事項
由于swift里面有嚴格的類型檢查,就比如在做手勢滑動的時候,手勢剛開始滑動的時候肯定需要記錄一下當前 器的位置我在項目中是定義的sumTime屬性是一個CMTime類型,如果在OC里大可不必這樣,來看一下swift與OC代碼的區(qū)別
swift寫法
/// 給sumTime初值 let time = self.player?.currentTime() self.sumTime = CMTimeMake((time?.value)!, (time?.timescale)!)
OC寫法
// 給sumTime初值 CMTime time = self.player.currentTime; self.sumTime = time.value/time.timescale;
滑動的距離是一個Double類型,而self.sumTime是CMTime類型,倆者肯定不能想加算出結(jié)束滑動的距離,所以將double類型轉(zhuǎn)換成CMTime類型用以下方法:
CMTime.init(seconds: Double.init(value/200), preferredTimescale: CMTimeScale(NSEC_PER_SEC))
如果是OC的話直接括號強轉(zhuǎn)類型即可實現(xiàn)。
知道滑動的距離和記錄滑動前的距離倆者想加即是當前位置,轉(zhuǎn)化成CMTime類型:
self.sumTime = CMTimeAdd(self.sumTime!, addend)
手勢是滑動了,但是進度條也是要跟著一起滑動的,有人說我把進度條刷新放到player的代理里面,手勢滑動完只需要把時間傳給 器, 器根據(jù)當前時間和總時間去更新進度條,這樣做也對,但是有一點就是,如果網(wǎng)速不好,手勢已經(jīng)滑動到5分鐘了,而進度條還停留在1分鐘的地方, 器緩存完畢了,進度條會瞬間跳到5分鐘,從而造成卡頓的假象體驗也不是很好,所以解決這個方法是手勢滑動的時候也更新進度條,但是手勢滑動的時候都是CMTime類型,怎么轉(zhuǎn)成Float類型,因為slider?.value是float類型。可以這樣:通過CMTimeGetSeconds方法得到一個Float64再通過Float.init方法得到一個float類型,看一下實現(xiàn):
let sliderTime = CMTimeGetSeconds(self.sumTime!)/CMTimeGetSeconds(totalMovieDuration) self.slider?.value = Float.init(sliderTime)
想查看整個過程可以看 器手勢添加與創(chuàng)建這一塊,我已經(jīng)用MARK:標記起來了。
設置控制面板信息
在視頻 過程中,對視頻的監(jiān)聽是必不可少的,監(jiān)聽 器狀態(tài), 器緩存...等,由于 器比較簡單,功能較少,剛開始我只監(jiān)聽了status屬性,后來我加上來loadedTimeRanges緩存狀態(tài),緩存這部分的緩存進度計算我已經(jīng)實現(xiàn)了,但是沒有用到只是簡單的打印了一下。
在對 器status屬性監(jiān)聽中加入了控制面板信息,是由MPNowPlayingInfoCenter來實現(xiàn)的,通過改變nowPlayingInfo里面對應的信息來更新面板信息,里面有好多屬性,比如MPMediaItemPropertyTitle設置音頻標題,MPMediaItemPropertyArtist作者、MPNowPlayingInfoPropertyElapsedPlaybackTime當前 過的時間、MPMediaItemPropertyPlaybackDuration 總時間等等。剛開始做的時候因為鎖屏要更新時間,而nowPlayingInfo又是一個字典類型的再加上需要更新界面布局的時間和進度條,直接將 器時間強制轉(zhuǎn)換成 string 類型,所以將這一部分放到了時間觀察里面,因為時間觀察會一直進行所以鎖屏界面信息也會一直更新,這樣帶來一個問題就是鎖屏界面的圖片如果是網(wǎng)絡圖片,每1秒就要請求一下圖片而且要不斷的更新這樣帶來的結(jié)果可想而知。后來才知道,將MPNowPlayingInfoPropertyElapsedPlaybackTime屬性設置成self.player!.currentTime() 器當前時間就會自動更新控制面板信息,調(diào)用的地方也很關鍵,必須放在 器已經(jīng) 的監(jiān)聽里面。
配置遠程控制顯示的信息
響應遠程控制是由MPRemoteCommandCenter來實現(xiàn)的,里面有很多屬性,比如:playCommand 響應事件、pauseCommand 暫停響應事件、nextTrackCommand下一曲響應事件、likeCommand喜歡按鈕,類似網(wǎng)易云音樂的那個鎖屏,如果設置了likeCommand則dislikeCommand是上一首響應事件、previousTrackCommand上一首,外部拖動進度條是changePlaybackPositionCommand,系統(tǒng)有一個專門的方法來出來遠程拖動進度條響應事件:
open func addTarget(handler: @escaping (MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus) -> Any
大概控制面板能用到的這些信息差不多也就這么多,如果想了解更多的可以看一下文檔或者查閱資料。
屏幕旋轉(zhuǎn)問題
一個視頻 實現(xiàn)起來并不困難,只要處理好player與platitem就行了。最難的就是,如果手機屏幕旋轉(zhuǎn),怎么能讓視頻跟著屏幕自適應呢,我在工程里面通過UIDevice變化添加的是屏幕旋轉(zhuǎn)監(jiān)聽:
/** * 監(jiān)聽設備旋轉(zhuǎn)通知 */ private func listeningRotating() { UIDevice.current.beginGeneratingDeviceOrientationNotifications() NotificationCenter.default.addObserver(self, selector: #selector(onDeviceOrientationChange), name:NSNotification.Name.UIDeviceOrientationDidChange, object: nil) }
如果用戶把屏幕旋轉(zhuǎn)關掉,就是控制中心那個開關,用戶旋轉(zhuǎn)屏幕,怎么能讓畫面跟著跑呢,我百度的很多資料,試了也很多方法,但是都不理想,用的還是OC的代碼,因為swift里面移除了NSInvocation屬性,用的依然是OC的屏幕強制旋轉(zhuǎn),只能使用橋接文件:
//這個方法是在網(wǎng)上找的 + (void)interfaceOrientation:(UIInterfaceOrientation)orientation{ if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) { SEL selector = NSSelectorFromString(@"setOrientation:"); NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]]; [invocation setSelector:selector]; [invocation setTarget:[UIDevice currentDevice]]; int val = orientation; // 從2開始是因為0 1 兩個參數(shù)已經(jīng)被selector和target占用 [invocation setArgument:&val atIndex:2]; [invocation invoke]; } }
因為做的是視頻 ,所以進入后臺后視頻會暫停,這個屬于正常現(xiàn)象,如果在視頻模式下,進入后臺利用控制面板是無法將視頻 的,如果在音頻模式下,進入后臺利用控制面板是可以讓視頻 的。大概就介紹這么多,一言半句也說得不是很明白,如果還有不明白的知識點可以去demo中自己去查,我也是一個初學者里面很多東西都是查資料得來的并不能保證其內(nèi)容的正確性。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對我們的支持。
上一篇:Swift如何調(diào)用Objective-C的可變參數(shù)函數(shù)詳解
欄 目:Swift
下一篇:swift中利用runtime交換方法的實現(xiàn)示例
本文標題:swift4.0實現(xiàn)視頻 、屏幕旋轉(zhuǎn)、倍速 、手勢調(diào)節(jié)及鎖屏面板等功能實例
本文地址:http://mengdiqiu.com.cn/a1/Swift/11951.html
您可能感興趣的文章
- 01-11Swift利用純代碼實現(xiàn)時鐘效果實例代碼
- 01-11Swift實現(xiàn)監(jiān)聽鍵盤通知及一些處理詳解
- 01-11swift中利用runtime交換方法的實現(xiàn)示例
- 01-11swift4 使用DrawerController實現(xiàn)側(cè)滑菜單功能的示例代碼
- 01-11Swift實現(xiàn)“或”操作符的3種方法示例
- 01-11Swift仿選擇電影票的效果并實現(xiàn)無限/自動輪播的方法
- 01-11Swift4.1轉(zhuǎn)場動畫實現(xiàn)側(cè)滑抽屜效果
- 01-11Swift使用CollectionView實現(xiàn)廣告欄滑動效果
- 01-11RxSwift實現(xiàn)替換delegate的方法示例


閱讀排行
本欄相關
- 01-11Swift利用Decodable解析JSON的一個小問題
- 01-11swift中defer幾個簡單的使用場景詳解
- 01-11Swift中初始化init的方法小結(jié)
- 01-11Swift中defer關鍵字推遲執(zhí)行示例詳解
- 01-11Swift利用純代碼實現(xiàn)時鐘效果實例代碼
- 01-11Swift中定義單例的方法實例
- 01-11Swift中排序算法的簡單取舍詳解
- 01-11Swift Json實例詳細解析
- 01-11Swift如何為設置中心添加常用功能
- 01-11Swift利用指紋識別或面部識別為應用添
隨機閱讀
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10C#中split用法實例總結(jié)
- 01-10SublimeText編譯C開發(fā)環(huán)境設置
- 01-11ajax實現(xiàn)頁面的局部加載
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文