iOS9學(xué)習(xí)系列:ReplayKit框架入門
ReplayKit簡(jiǎn)介
在iOS 9中,ReplayKit 是一款全新的框架,可謂是游戲開發(fā)者(開發(fā)商)的福音。它可以讓玩家更便捷地記錄游戲進(jìn)度或數(shù)據(jù)以及分享的功能。除此之外更強(qiáng)大的是:ReplayKit為用戶(玩家)提供了一個(gè)全功能的交互界面,用戶可用它來(lái)編輯或制作自己的視頻剪輯!
ReplayKit不需要太大電量損耗和性能損耗就可以產(chǎn)出高清的視頻記錄。ReplayKit支持使用A7芯片以上,操作系統(tǒng)為iOS 9或更高版本的設(shè)備。
您需要準(zhǔn)備什么
本教程要求您的Xcode版本為7.0以上,OS X為Yosemite(10.10.x)以上。倘若您還想在您的設(shè)備上體驗(yàn)一下這個(gè)簡(jiǎn)易的工程,請(qǐng)確保您的設(shè)備可以滿足ReplayKit所需要的軟硬件要求,當(dāng)然您還需在GitHub上下載工程源碼。
啟動(dòng)錄制
ReplayKit框架提供了RPScreenRecorder類以及類單例方法sharedRecorder()供您進(jìn)行游戲錄制。這個(gè)實(shí)例對(duì)象負(fù)責(zé)檢查設(shè)備的記錄功能,包括啟動(dòng)、停止以及丟棄記錄,并可以選擇啟動(dòng)麥克風(fēng)讓玩家錄制真人語(yǔ)音解說!
打開從GitHub下載的初始工程中GameViewController.swift文件。在文件頂部,導(dǎo)入ReplayKit框架。
- import ReplayKit
接下來(lái),在用戶按下Start Recording按鈕時(shí)調(diào)用GameViewController類中的startRecording(_:)這個(gè)方法開始錄制。
- func startRecording(sender: UIButton) {
- if RPScreenRecorder.sharedRecorder().available {
- RPScreenRecorder.sharedRecorder().startRecordingWithMicrophoneEnabled(true, handler: { (error:
- NSError?) -> Void in
- if error == nil { // Recording has started
- sender.removeTarget(self, action: "startRecording:", forControlEvents: .TouchUpInside)
- sender.addTarget(self, action: "stopRecording:", forControlEvents: .TouchUpInside)
- sender.setTitle("Stop Recording", forState: .Normal)
- sender.setTitleColor(UIColor.redColor(), forState: .Normal)
- } else {
- // Handle error
- }
- })
- } else {
- // Display UI for recording being unavailable
- }
- }
跟著代碼一步一步走。我們通過sharedRecorder()方法訪問RPScreenRecorder實(shí)例以檢查我們的設(shè)備錄制功能是否可用。如果功能可用,我們便可以通過調(diào)用startRecordingWithMicrophone(_:handler:)方法啟動(dòng)一段記錄。此方法的***個(gè)參數(shù)為BOOL類型值,表示是否開啟設(shè)備的麥克風(fēng),第二個(gè)參數(shù)則為完成后回調(diào)的代碼塊。如果出現(xiàn)一些錯(cuò)誤,RepalyKit框架可以通過代碼塊返回給你并提示您錯(cuò)誤的信息。如果一切準(zhǔn)備就緒,我們改變按鈕的式樣告知用戶錄制已開始,再次點(diǎn)擊可以停止錄制。
編譯運(yùn)行你的應(yīng)用程序并嘗試按下綠色按鈕,你會(huì)看到類似一團(tuán)火焰的粒子效果,如果你點(diǎn)擊Start Recording,你會(huì)看到這樣的警告,如圖:
注意,這個(gè)警告每次會(huì)在你開始錄制時(shí)出現(xiàn)。然而,一旦用戶選擇了其中一種偏好設(shè)置,系統(tǒng)會(huì)在接下來(lái)的8分鐘記住這個(gè)選擇。
在你選擇選項(xiàng)之后,Start Recording按鈕變?yōu)榱思t色的Stop Recording按鈕。
停止,丟棄和編輯記錄
現(xiàn)在,我們的app可以開始ReplayKit的錄制,是時(shí)候去了解在完成的時(shí)候編寫怎樣的代碼了。在GameViewController類中實(shí)現(xiàn)stopRecording(_:)這個(gè)方法:
- func stopRecording(sender: UIButton) {
- RPScreenRecorder.sharedRecorder().stopRecordingWithHandler { (previewController: RPPreviewViewController?, error: NSError?) -> Void in
- if previewController != nil {
- let alertController = UIAlertController(title: "Recording", message: "Do you wish to discard or view your gameplay recording?", preferredStyle: .Alert)
- let discardAction = UIAlertAction(title: "Discard", style: .Default) { (action: UIAlertAction) in
- RPScreenRecorder.sharedRecorder().discardRecordingWithHandler({ () -> Void in
- // Executed once recording has successfully been discarded
- })
- }
- let viewAction = UIAlertAction(title: "View", style: .Default, handler: { (action: UIAlertAction) -> Void in
- self.presentViewController(previewController!, animated: true, completion: nil)
- })
- alertController.addAction(discardAction)
- alertController.addAction(viewAction)
- self.presentViewController(alertController, animated: true, completion: nil)
- sender.removeTarget(self, action: "stopRecording:", forControlEvents: .TouchUpInside)
- sender.addTarget(self, action: "startRecording:", forControlEvents: .TouchUpInside)
- sender.setTitle("Start Recording", forState: .Normal)
- sender.setTitleColor(UIColor.blueColor(), forState: .Normal)
- } else {
- // Handle error
- }
- }
- }
繼續(xù)一步一步地研究這個(gè)方法的實(shí)現(xiàn)。我們還是用RPScreenRecorder的實(shí)例對(duì)象調(diào)用stopRecordingWithHandler(_:)這個(gè)方法,這次在回調(diào)的塊中,我們通過檢查previewController存不存在來(lái)判斷app完成錄制的成功與否。
我們創(chuàng)建一個(gè)UIAlertController,它有兩個(gè)action,一個(gè)為丟棄記錄,另一個(gè)為回看記錄。選擇丟棄記錄則調(diào)用discardRecordingWithHandler(_:)這個(gè)方法。要注意的是,這個(gè)方法只能在確保錄制成功地完成后才可以調(diào)用,要是在錄制進(jìn)行的時(shí)候就調(diào)用的話,雖然系統(tǒng)不會(huì)拋出任何錯(cuò)誤,但是也不會(huì)丟棄任何記錄。
選擇回看記錄,我們就呈現(xiàn)previewController視圖,它是RPPreviewController類的實(shí)例,從stopRecordingWithHandler(_:)方法回調(diào)塊中返回給我們,用來(lái)回看、編輯或分享記錄。這個(gè)previewController視圖控制器實(shí)例是唯一能夠訪問到由ReplayKit生成的視頻文件,它的職能就是負(fù)責(zé)保存/分享記錄。
***,別忘了恢復(fù)startRecording按鈕以便再次另一段記錄的開始!
編譯和運(yùn)行你的應(yīng)用程序并點(diǎn)擊開始錄制。一旦按下Stop Recording按鈕,你會(huì)看到如下的彈出窗:
如果你選擇了view選項(xiàng),會(huì)呈現(xiàn)如下的視圖控制器:
在這里,你可以編輯你的錄像并可以點(diǎn)擊Save按鈕選擇轉(zhuǎn)存到你的“照片”中。當(dāng)然你也可以點(diǎn)擊左下角的分享按鈕分享你的錄制視頻。
需要注意的是,不管是由于設(shè)計(jì)的原因還是ReplayKit框架的bug,在保存到“照片”的時(shí)候沒有確認(rèn)的過程就直接進(jìn)行了保存。
排除界面元素
你可能已經(jīng)注意到了頂部和底部的按鈕在應(yīng)用錄制的記錄中都是可見的,它們包含在了最終的視頻記錄中。當(dāng)RepalyKit錄制你的應(yīng)用時(shí),它毫不遺漏地記錄了應(yīng)用程序在UIWindow中渲染的一切視圖,任何細(xì)節(jié)都不掩飾地記錄。還好,RepalyKit可以在來(lái)電話是或用戶輸入時(shí)的界面停止錄制。
從記錄中排除的用戶界面元素,你需要把它們放置在單獨(dú)的UIWindow實(shí)例中。讓我們研究下它是如何工作的。在GameViewController類中添加一個(gè)屬性buttonWindow,類型為UIWindow!
- var buttonWindow: UIWindow!
下一步,用以下代碼取代GameViewController類中的addButtons(_:)方法:
- func addButtons(buttons: [UIButton]) {
- self.buttonWindow = UIWindow(frame: self.view.frame)
- self.buttonWindow.rootViewController = HiddenStatusBarViewController()
- for button in buttons {
- self.buttonWindow.rootViewController?.view.addSubview(button)
- }
- self.buttonWindow.makeKeyAndVisible()
- }
在 addButton(_:)方法中,我們新創(chuàng)建了一個(gè)新的UIWindow對(duì)象,并給它加了一些按鈕然后讓它可見。注意HiddenStatusBarViewController類是我們?cè)诔跏脊こ讨屑尤氲囊粋€(gè)自定義的視圖控制器,它用來(lái)確保在新的窗口隱藏屏幕上方的狀態(tài)欄。
***,用以下的代碼補(bǔ)全stopRecording(_:)方法的實(shí)現(xiàn)部分:
- func stopRecording(sender: UIButton) {
- RPScreenRecorder.sharedRecorder().stopRecordingWithHandler { (previewController: RPPreviewViewController?, error: NSError?) -> Void in
- if previewController != nil {
- let alertController = UIAlertController(title: "Recording", message: "Do you wish to discard or view your gameplay recording?", preferredStyle: .Alert)
- let discardAction = UIAlertAction(title: "Discard", style: .Default) { (action: UIAlertAction) in
- RPScreenRecorder.sharedRecorder().discardRecordingWithHandler({ () -> Void in
- // Executed once recording has successfully been discarded
- })
- }
- let viewAction = UIAlertAction(title: "View", style: .Default, handler: { (action: UIAlertAction) -> Void in
- self.buttonWindow.rootViewController?.presentViewController(previewController!, animated: true, completion: nil)
- })
- alertController.addAction(discardAction)
- alertController.addAction(viewAction)
- print(self.buttonWindow.rootViewController)
- self.buttonWindow.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
- sender.removeTarget(self, action: "stopRecording:", forControlEvents: .TouchUpInside)
- sender.addTarget(self, action: "startRecording:", forControlEvents: .TouchUpInside)
- sender.setTitle("Start Recording", forState: .Normal)
- sender.setTitleColor(UIColor.blueColor(), forState: .Normal)
- } else {
- // Handle error
- }
- }
- }
新的視圖控制器唯一不同于之前的是窗口頂端的交互部分。它確保了交互控件正確的顯示與用戶交互的正確執(zhí)行。
再次運(yùn)行你的應(yīng)用,并進(jìn)行新的錄制,你會(huì)發(fā)現(xiàn)界面按鈕都隱藏了:
委托協(xié)議
還有與ReplayKit關(guān)聯(lián)的兩個(gè)協(xié)議共四個(gè)代理方法,不過本教程沒有用到,但我們應(yīng)該了解應(yīng)當(dāng)怎樣使用它們。
RPScreenRecorderDelegate協(xié)議定義了以下兩個(gè)方法:
- screenRecorder(_:didStopRecordingWithError:previewViewController:) 不管何時(shí),只要錄制過程中出現(xiàn)了錯(cuò)誤就會(huì)調(diào)用這個(gè)方法。當(dāng)然如果ReplayKit能夠從這個(gè)錯(cuò)誤自我修復(fù)并完成錄制,你仍可以選擇將預(yù)覽視圖呈現(xiàn)給用戶。
- screenRecorderDidChangeAvailability(_:) 這個(gè)方法在觸發(fā)另一個(gè)action引發(fā)錄制狀態(tài)改變時(shí)回調(diào)。舉個(gè)例子,當(dāng)你連接或斷開Airplay時(shí),就會(huì)觸發(fā)此方法。
- RPPreviewViewControllerDelegate協(xié)議定義了以下方法:
- previewViewControllerDidFinlish(_:) 這個(gè)方法會(huì)在用戶退出RPPreviewViewController視圖實(shí)例的時(shí)候立刻調(diào)用。
- previewViewController(_:didFinlishWithActivityTypes:) 這個(gè)方法會(huì)在previewViewControllerDidFinlish(_:)回調(diào)的同時(shí)觸發(fā),只不過這個(gè)方法攜帶了一個(gè)額外的UIActivity類型的參數(shù)。
需要注意的是,如果你實(shí)現(xiàn)了任意的RPPreviewViewControllerDelegate的方法,你就需要負(fù)責(zé)在適當(dāng)?shù)臅r(shí)候推出previewViewController視圖控制器。
要點(diǎn)
在即將完成時(shí),你還需要注意使用RepalyKit時(shí)的一些關(guān)鍵的要點(diǎn)。
- 每個(gè)應(yīng)用程序在任何時(shí)間只可以存儲(chǔ)一條記錄。一旦你開始錄制一條新的記錄,如果之前的記錄已存在,那么新的會(huì)自動(dòng)覆蓋掉之前的記錄!
- 及時(shí)地丟棄不必要的記錄。確保沒有太多不必要的視頻數(shù)據(jù)占用設(shè)備的本地存儲(chǔ)空間,從用戶的行為中一旦判斷出一條記錄沒有價(jià)值時(shí),及時(shí)地丟棄它。在本教程中,在用戶不需要記錄的情況下,教程也給出了***的實(shí)現(xiàn)邏輯那就是丟棄它。
- 顯示錄制指示器。正如本教程中,顯示指示器可以提示用戶視頻是否在錄制,尤其在同時(shí)使用設(shè)備的麥克風(fēng)的情況下,盡可能地提高用戶體驗(yàn)。
- 仔細(xì)選擇要從用戶的錄制交互界面排除的元素,把選擇界面的元素放置在單獨(dú)的窗口中,包括用以選擇的控件或者偏離游戲本身那些不重要的東西。如:記錄指示器,虛擬控制或菜單按鈕。
- 你不能直接訪問最終的視頻文件。通過用戶回看視圖控制器previewViewController你才可以使ReplayKit的記錄存儲(chǔ)的數(shù)據(jù)可見。但由于蘋果對(duì)用戶隱私保護(hù),ReplayKit的記錄數(shù)據(jù)都應(yīng)由應(yīng)用程序來(lái)訪問。如果你想上傳這些記錄到你自己的服務(wù)器,你需要?jiǎng)?chuàng)建一個(gè)共享的擴(kuò)展視圖控制器來(lái)完成,并從previewViewController中呈現(xiàn)出來(lái)。
- ReplayKit也支持家長(zhǎng)控制功能。即使設(shè)備當(dāng)前后臺(tái)沒有其他的進(jìn)程在運(yùn)行,錄制功能是否可用仍然收到家長(zhǎng)控制的授權(quán)。這就意味著你要保證在錄制開始檢查功能是否被允許使用。
- ***要說的是,盡管蘋果已經(jīng)向游戲開發(fā)者(開發(fā)商)做好了用ReplayKit使用戶分享他們的游戲的準(zhǔn)備,但你可以在任何蘋果應(yīng)用中使用ReplayKit,只要滿足Xcode 7+和iOS 9+的要求。我非常地支持使用ReplayKit這一優(yōu)秀的框架,我很樂意看到更多開發(fā)者可以使用它,做出更多更好的蘋果應(yīng)用!
總結(jié)
你現(xiàn)在應(yīng)該很樂意在你的app中集成ReplayKit框架完成屏幕錄制功能了,它可以輕松編輯你的用戶共享??偟膩?lái)說,ReplayKit是非常出色非常強(qiáng)大的框架,是一款***的應(yīng)用程序的屏幕錄制及共享的工具!