Feel Physics Backyard


アプリの画面を動画として保存する 罠だらけ(iOS9)



ReplayKit Framework has added from iOS9 for the purpose of saving the game play video. At first glance, it is simple enough, but if you use this, in fact, be full of traps, such as the need of thread control.


Including overseas, articles introducing ReplayKit is usually written as follows.


You can easily save the play video as follows:

import ReplayKit

// start recording
.startRecordingWithMicrophoneEnabled(false, handler: { error in })

// stop recording
.stopRecordingWithHandler { viewController, error in
    self.presentViewController(viewController!, animated: true, completion: nil)


Oh, this is simple enough. In practice, however there was a trap of a number:

  • start recordingしてから実際にrecording has startedまでに3秒くらいかかる
  • stop recordingすると保存画面が表示されるが、「save」「cancel」共に押しても何も起こらない
  • プロトコルを指定すると保存できるようになるが、「保存」を押してから保存画面が消えるまでに時間がかかり、しかもそのあいだ何回も(同じ動画を)保存できてしまう
  • 最終的にはメインスレッドを呼んで保存画面を消さなければならない

  • It takes about 3 seconds among "start recording" and "recording has started".
  • When stop recording, save screen is displayed. But nothing happens when I press the "save", "cancel" button.
  • When I specified the protocol, I've got to be able to save, but it takes a long time before save screen disappears after pressing the "Save", yet I can save it (the same video) for many times during the time.
  • After all, I had to call the main thread to erase the save screen.


Eventually it became the code, such as the following. Where is the easy!

import ReplayKit

// プロトコルを指定する
// specify protocol
class ViewController: UIViewController, RPPreviewViewControllerDelegate {
    var isRecording = false
    var previewController: RPPreviewViewController!

    @IBAction func RecordPressed(sender: AnyObject) {
        if isRecording {
            isRecording = false
            print("record stopped")
            RPScreenRecorder.sharedRecorder().stopRecordingWithHandler { previewController, error in
                // 保存画面のボタンを押すとメッセージがselfに刺さるようにする
                // let message hit self when I push the button on save screen
                previewController?.previewControllerDelegate = self
                self.previewController = previewController;
                self.presentViewController(previewController!, animated: true, completion: nil)
        } else {
            isRecording = true
            print("prepare to record")
            RPScreenRecorder.sharedRecorder().startRecordingWithMicrophoneEnabled(true) { error in
                print("recording started")

    // プロトコルを指定して、保存画面の「保存」「キャンセル」を受け取るようにする
    // specify protocol and recieve "save" "cancel" from save screen
    func previewControllerDidFinish(previewController: RPPreviewViewController) {
        // そのままだと5秒くらい保存画面が残り、多重保存もできてしまうので、メインスレッドで実行
        // save screen remains about 5 seconds and you can save the same video many times, so run on main thread
        dispatch_async(dispatch_get_main_queue()) { [unowned previewController] in
            // close preview window
            previewController.dismissViewControllerAnimated(true, completion: nil)


With the code of article below I've made code runs correctly. Thanks!

iOS 9 の新機能のサンプルコード集『iOS-9-Sampler』を公開しました - Over&Out その後