iOS9學(xué)習(xí)系列:ReplayKit框架入門
ReplayKit簡介
在iOS 9中,ReplayKit 是一款全新的框架,可謂是游戲開發(fā)者(開發(fā)商)的福音。它可以讓玩家更便捷地記錄游戲進度或數(shù)據(jù)以及分享的功能。除此之外更強大的是:ReplayKit為用戶(玩家)提供了一個全功能的交互界面,用戶可用它來編輯或制作自己的視頻剪輯!
ReplayKit不需要太大電量損耗和性能損耗就可以產(chǎn)出高清的視頻記錄。ReplayKit支持使用A7芯片以上,操作系統(tǒng)為iOS 9或更高版本的設(shè)備。
您需要準(zhǔn)備什么
本教程要求您的Xcode版本為7.0以上,OS X為Yosemite(10.10.x)以上。倘若您還想在您的設(shè)備上體驗一下這個簡易的工程,請確保您的設(shè)備可以滿足ReplayKit所需要的軟硬件要求,當(dāng)然您還需在GitHub上下載工程源碼。
啟動錄制
ReplayKit框架提供了RPScreenRecorder類以及類單例方法sharedRecorder()供您進行游戲錄制。這個實例對象負(fù)責(zé)檢查設(shè)備的記錄功能,包括啟動、停止以及丟棄記錄,并可以選擇啟動麥克風(fēng)讓玩家錄制真人語音解說!
打開從GitHub下載的初始工程中GameViewController.swift文件。在文件頂部,導(dǎo)入ReplayKit框架。
- import ReplayKit
接下來,在用戶按下Start Recording按鈕時調(diào)用GameViewController類中的startRecording(_:)這個方法開始錄制。
- 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è)備錄制功能是否可用。如果功能可用,我們便可以通過調(diào)用startRecordingWithMicrophone(_:handler:)方法啟動一段記錄。此方法的***個參數(shù)為BOOL類型值,表示是否開啟設(shè)備的麥克風(fēng),第二個參數(shù)則為完成后回調(diào)的代碼塊。如果出現(xiàn)一些錯誤,RepalyKit框架可以通過代碼塊返回給你并提示您錯誤的信息。如果一切準(zhǔn)備就緒,我們改變按鈕的式樣告知用戶錄制已開始,再次點擊可以停止錄制。
編譯運行你的應(yīng)用程序并嘗試按下綠色按鈕,你會看到類似一團火焰的粒子效果,如果你點擊Start Recording,你會看到這樣的警告,如圖:
注意,這個警告每次會在你開始錄制時出現(xiàn)。然而,一旦用戶選擇了其中一種偏好設(shè)置,系統(tǒng)會在接下來的8分鐘記住這個選擇。
在你選擇選項之后,Start Recording按鈕變?yōu)榱思t色的Stop Recording按鈕。
停止,丟棄和編輯記錄
現(xiàn)在,我們的app可以開始ReplayKit的錄制,是時候去了解在完成的時候編寫怎樣的代碼了。在GameViewController類中實現(xiàn)stopRecording(_:)這個方法:
- 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ù)一步一步地研究這個方法的實現(xiàn)。我們還是用RPScreenRecorder的實例對象調(diào)用stopRecordingWithHandler(_:)這個方法,這次在回調(diào)的塊中,我們通過檢查previewController存不存在來判斷app完成錄制的成功與否。
我們創(chuàng)建一個UIAlertController,它有兩個action,一個為丟棄記錄,另一個為回看記錄。選擇丟棄記錄則調(diào)用discardRecordingWithHandler(_:)這個方法。要注意的是,這個方法只能在確保錄制成功地完成后才可以調(diào)用,要是在錄制進行的時候就調(diào)用的話,雖然系統(tǒng)不會拋出任何錯誤,但是也不會丟棄任何記錄。
選擇回看記錄,我們就呈現(xiàn)previewController視圖,它是RPPreviewController類的實例,從stopRecordingWithHandler(_:)方法回調(diào)塊中返回給我們,用來回看、編輯或分享記錄。這個previewController視圖控制器實例是唯一能夠訪問到由ReplayKit生成的視頻文件,它的職能就是負(fù)責(zé)保存/分享記錄。
***,別忘了恢復(fù)startRecording按鈕以便再次另一段記錄的開始!
編譯和運行你的應(yīng)用程序并點擊開始錄制。一旦按下Stop Recording按鈕,你會看到如下的彈出窗:
如果你選擇了view選項,會呈現(xiàn)如下的視圖控制器:
在這里,你可以編輯你的錄像并可以點擊Save按鈕選擇轉(zhuǎn)存到你的“照片”中。當(dāng)然你也可以點擊左下角的分享按鈕分享你的錄制視頻。
需要注意的是,不管是由于設(shè)計的原因還是ReplayKit框架的bug,在保存到“照片”的時候沒有確認(rèn)的過程就直接進行了保存。
排除界面元素
你可能已經(jīng)注意到了頂部和底部的按鈕在應(yīng)用錄制的記錄中都是可見的,它們包含在了最終的視頻記錄中。當(dāng)RepalyKit錄制你的應(yīng)用時,它毫不遺漏地記錄了應(yīng)用程序在UIWindow中渲染的一切視圖,任何細(xì)節(jié)都不掩飾地記錄。還好,RepalyKit可以在來電話是或用戶輸入時的界面停止錄制。
從記錄中排除的用戶界面元素,你需要把它們放置在單獨的UIWindow實例中。讓我們研究下它是如何工作的。在GameViewController類中添加一個屬性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)建了一個新的UIWindow對象,并給它加了一些按鈕然后讓它可見。注意HiddenStatusBarViewController類是我們在初始工程中加入的一個自定義的視圖控制器,它用來確保在新的窗口隱藏屏幕上方的狀態(tài)欄。
***,用以下的代碼補全stopRecording(_:)方法的實現(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īng)用,并進行新的錄制,你會發(fā)現(xiàn)界面按鈕都隱藏了:
委托協(xié)議
還有與ReplayKit關(guān)聯(lián)的兩個協(xié)議共四個代理方法,不過本教程沒有用到,但我們應(yīng)該了解應(yīng)當(dāng)怎樣使用它們。
RPScreenRecorderDelegate協(xié)議定義了以下兩個方法:
- screenRecorder(_:didStopRecordingWithError:previewViewController:) 不管何時,只要錄制過程中出現(xiàn)了錯誤就會調(diào)用這個方法。當(dāng)然如果ReplayKit能夠從這個錯誤自我修復(fù)并完成錄制,你仍可以選擇將預(yù)覽視圖呈現(xiàn)給用戶。
- screenRecorderDidChangeAvailability(_:) 這個方法在觸發(fā)另一個action引發(fā)錄制狀態(tài)改變時回調(diào)。舉個例子,當(dāng)你連接或斷開Airplay時,就會觸發(fā)此方法。
- RPPreviewViewControllerDelegate協(xié)議定義了以下方法:
- previewViewControllerDidFinlish(_:) 這個方法會在用戶退出RPPreviewViewController視圖實例的時候立刻調(diào)用。
- previewViewController(_:didFinlishWithActivityTypes:) 這個方法會在previewViewControllerDidFinlish(_:)回調(diào)的同時觸發(fā),只不過這個方法攜帶了一個額外的UIActivity類型的參數(shù)。
需要注意的是,如果你實現(xiàn)了任意的RPPreviewViewControllerDelegate的方法,你就需要負(fù)責(zé)在適當(dāng)?shù)臅r候推出previewViewController視圖控制器。
要點
在即將完成時,你還需要注意使用RepalyKit時的一些關(guān)鍵的要點。
- 每個應(yīng)用程序在任何時間只可以存儲一條記錄。一旦你開始錄制一條新的記錄,如果之前的記錄已存在,那么新的會自動覆蓋掉之前的記錄!
- 及時地丟棄不必要的記錄。確保沒有太多不必要的視頻數(shù)據(jù)占用設(shè)備的本地存儲空間,從用戶的行為中一旦判斷出一條記錄沒有價值時,及時地丟棄它。在本教程中,在用戶不需要記錄的情況下,教程也給出了***的實現(xiàn)邏輯那就是丟棄它。
- 顯示錄制指示器。正如本教程中,顯示指示器可以提示用戶視頻是否在錄制,尤其在同時使用設(shè)備的麥克風(fēng)的情況下,盡可能地提高用戶體驗。
- 仔細(xì)選擇要從用戶的錄制交互界面排除的元素,把選擇界面的元素放置在單獨的窗口中,包括用以選擇的控件或者偏離游戲本身那些不重要的東西。如:記錄指示器,虛擬控制或菜單按鈕。
- 你不能直接訪問最終的視頻文件。通過用戶回看視圖控制器previewViewController你才可以使ReplayKit的記錄存儲的數(shù)據(jù)可見。但由于蘋果對用戶隱私保護,ReplayKit的記錄數(shù)據(jù)都應(yīng)由應(yīng)用程序來訪問。如果你想上傳這些記錄到你自己的服務(wù)器,你需要創(chuàng)建一個共享的擴展視圖控制器來完成,并從previewViewController中呈現(xiàn)出來。
- ReplayKit也支持家長控制功能。即使設(shè)備當(dā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框架完成屏幕錄制功能了,它可以輕松編輯你的用戶共享??偟膩碚f,ReplayKit是非常出色非常強大的框架,是一款***的應(yīng)用程序的屏幕錄制及共享的工具!