ReplayKit简介

在iOS 9中,ReplayKit 是一款全新的框架,可谓是游戏开发者(开发商)的福音。它可以让玩家更便捷地记录游戏进度或数据以及分享的功能。除此之外更强大的是:ReplayKit为用户(玩家)提供了一个全功能的交互界面,用户可用它来编辑或制作自己的视频剪辑!

ReplayKit不需要太大电量损耗和性能损耗就可以产出高清的视频记录。ReplayKit支持使用A7芯片以上,操作系统为iOS 9或更高版本的设备。

准备工作

本教程要求Xcode版本为7.0以上,OS X为Yosemite(10.10.x)以上。倘若您还想在您的设备上体验一下这个简易的工程,请确保您的设备可以满足ReplayKit所需要的软硬件要求,当然您还需在GitHub上下载工程源码。

启动录制

ReplayKit框架提供了RPScreenRecorder类以及类单例方法sharedRecorder()供您进行游戏录制。这个实例对象负责检查设备的记录功能,包括启动、停止以及丢弃记录,并可以选择启动麦克风让玩家录制真人语音解说!

  • 打开从GitHub下载的初始工程中GameViewController.swift文件。在文件顶部,导入ReplayKit框架。
import ReplayKit
  • 按下Start Recording按钮时调用GameViewController类中的startRecording(_:)这个方法开始录制
func startRecording(sender: UIButton) {if RPScreenRecorder.sharedRecorder().available {RPScreenRecorder.sharedRecorder().startRecordingWithMicrophoneEnabled(true, handler: { (error: NSError?) -> Void inif error == nil { // Recording has startedsender.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实例以检查我们的设备录制功能是否可用。如果功能可用,我们便可以通过调用startRecordingWithMicrophone(_:handler:)方法启动一段记录。此方法的第一个参数为BOOL类型值,表示是否开启设备的麦克风,第二个参数则为完成后回调的代码块。如果出现一些错误,RepalyKit框架可以通过代码块返回给你并提示你错误的信息。如果一切准备就绪,我们改变按钮的式样告知用户录制已开始,再次点击可以停止录制。

  • 编译运行你的应用程序并尝试按下绿色按钮,你会看到类似一团火焰的粒子效果,如果你点击Start Recording,你会看到这样的警告,如图:

注意,这个警告每次会在你开始录制时出现。然而,一旦用户选择了其中一种偏好设置,系统会在接下来的8分钟记住这个选择。在你选择选项之后,Start Recording按钮变为了红色的Stop Recording按钮。

停止,丢弃和编辑记录

  • App开始ReplayKit的录制,是时候去了解在完成的时候编写怎样的代码了。在GameViewController类中实现stopRecording(_:)这个方法:
func stopRecording(sender: UIButton) {RPScreenRecorder.sharedRecorder().stopRecordingWithHandler { (previewController: RPPreviewViewController?, error: NSError?) -> Void inif 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) inRPScreenRecorder.sharedRecorder().discardRecordingWithHandler({ () -> Void in// Executed once recording has successfully been discarded})}let viewAction = UIAlertAction(title: "View", style: .Default, handler: { (action: UIAlertAction) -> Void inself.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}}
}
  • 用RPScreenRecorder的实例对象调用stopRecordingWithHandler(_:)这个方法,这次在回调的块中,通过检查previewController存不存在来判断app完成录制的成功与否。

  • 创建一个UIAlertController,它有两个action,一个为丢弃记录,另一个为回看记录,选择丢弃记录则调用discardRecordingWithHandler(_:)这个方法。要注意的是,这个方法只能在确保录制成功地完成后才可以调用,要是在录制进行的时候就调用的话,虽然系统不会抛出任何错误,但是也不会丢弃任何记录。

  • 选择回看记录,就呈现previewController视图,它是RPPreviewController类的实例,从stopRecordingWithHandler(_:)方法回调块中返回,用来回看编辑或分享记录。这个previewController视图控制器实例是唯一能够访问到由ReplayKit生成的视频文件,它的职能就是负责保存/分享记录。

  • 恢复startRecording按钮以便再次另一段记录的开始。编译和运行你的应用程序并点击开始录制。一旦按下Stop Recording按钮,你会看到如下的弹出窗:

  • 如果你选择了view选项,会呈现如下的视图控制器:

  • 在这里,你可以编辑你的录像并可以点击Save按钮选择转存到你的“照片”中。当然你也可以点击左下角的分享按钮分享你的录制视频。需要注意的是,不管是由于设计的原因还是ReplayKit框架的bug,在保存到“照片”的时候没有确认的过程就直接进行了保存。

排除界面元素

你可能已经注意到了顶部和底部的按钮在应用录制的记录中都是可见的,它们包含在了最终的视频记录中。当RepalyKit录制你的应用时,它毫不遗漏地记录了应用程序在UIWindow中渲染的一切视图,任何细节都不掩饰地记录。还好,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(_:)方法中,新创建了一个新的UIWindow对象,并给它加了一些按钮然后让它可见。注意HiddenStatusBarViewController类是在初始工程中加入的一个自定义的视图控制器,它用来确保在新的窗口隐藏屏幕上方的状态栏。

  • 用以下的代码补全stopRecording(_:)方法的实现部分:新的视图控制器唯一不同于之前的是窗口顶端的交互部分。它确保了交互控件正确的显示与用户交互的正确执行。

func stopRecording(sender: UIButton) {RPScreenRecorder.sharedRecorder().stopRecordingWithHandler { (previewController: RPPreviewViewController?, error: NSError?) -> Void inif 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) inRPScreenRecorder.sharedRecorder().discardRecordingWithHandler({ () -> Void in// Executed once recording has successfully been discarded})}let viewAction = UIAlertAction(title: "View", style: .Default, handler: { (action: UIAlertAction) -> Void inself.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}}
}
  • 再次运行你的应用,并进行新的录制,你会发现界面按钮都隐藏了:

委托协议