<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>ReplayKit – IMG.LY Blog</title><description>Posts tagged ReplayKit on the IMG.LY blog.</description><link>https://img.ly/blog/tag/replaykit/</link><language>en-us</language><image><url>https://img.ly/apple-touch-icon.png</url><title>ReplayKit – IMG.LY Blog</title><link>https://img.ly/blog/tag/replaykit/</link></image><atom:link href="https://img.ly/blog/tag/replaykit/rss.xml" rel="self" type="application/rss+xml"/><generator>Astro</generator><lastBuildDate>Wed, 24 Jun 2026 09:29:46 GMT</lastBuildDate><ttl>60</ttl><item><title>How To Record Screen Video Using ReplayKit for iOS</title><link>https://img.ly/blog/record-screen-with-swift-replaykit/</link><guid isPermaLink="true">https://img.ly/blog/record-screen-with-swift-replaykit/</guid><description>Use Swift and ReplayKit to add screen recording to your application. Also use the new rolling clips feature introduced in iOS 15!</description><pubDate>Tue, 21 Sep 2021 15:05:08 GMT</pubDate><content:encoded>&lt;p&gt;In this article, you will see how to use Swift and &lt;code&gt;ReplayKit&lt;/code&gt; to add screen recording to your application. You will also see how to use the new rolling clips feature, introduced in iOS 15. The code in this article uses Swift 5 and Xcode 13. Clone &lt;a href=&quot;https://github.com/waltertyree/replay-screen-video&quot;&gt;this repository&lt;/a&gt; for a sample project and example code.&lt;/p&gt;
&lt;h2 id=&quot;replaykit-basics&quot;&gt;ReplayKit Basics&lt;/h2&gt;
&lt;p&gt;Apple introduced the &lt;code&gt;ReplayKit&lt;/code&gt; framework in 2015 with iOS 9. They have refined and expanded it since then, but it still has a small API. &lt;code&gt;ReplayKit&lt;/code&gt; uses the same shared components as AirPlay and the device screen recorder (accessible from the device Control Center). For this reason, &lt;code&gt;ReplayKit&lt;/code&gt; functions will not work when using AirPlay or playing video. Also, the screen recording functions do not work on the Xcode simulators. You should test using a physical device.&lt;/p&gt;
&lt;p&gt;Your app makes all its calls to the &lt;code&gt;RPScreenRecorder.shared()&lt;/code&gt; object. This is a singleton object for your app that &lt;code&gt;ReplayKit&lt;/code&gt; provides. There is no need to store it in a variable or pass it around in your code.&lt;/p&gt;
&lt;h2 id=&quot;rolling-clip-recording&quot;&gt;Rolling Clip Recording&lt;/h2&gt;
&lt;p&gt;In iOS 15, Apple introduced rolling clip recording. &lt;code&gt;ReplayKit&lt;/code&gt; will maintain an updated video buffer of the most recent fifteen seconds. Your app can request the video at any time. &lt;code&gt;ReplayKit&lt;/code&gt; comes from &lt;code&gt;GameCenter&lt;/code&gt;. Apple’s idea for this feature is for creating a short, sharable video of the moments before an exciting event in a game. Another use can be for a user to record the steps leading up to a defect during testing. When the user is unlikely to know in advance that they will want a screen recording, rolling clips may be a good solution.&lt;/p&gt;
&lt;p&gt;To start rolling clip buffering, include a method such as this one&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;RPScreenRecorder.&lt;/span&gt;&lt;span&gt;shared&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;startClipBuffering&lt;/span&gt;&lt;span&gt; { err &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if&lt;/span&gt;&lt;span&gt; let&lt;/span&gt;&lt;span&gt; err &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; err {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    //either the user denied permission or something like&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    //AVPlayer or AirPlay is using the shared recorder resources.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Error attempting to start buffering &lt;/span&gt;&lt;span&gt;\(err.&lt;/span&gt;&lt;span&gt;localizedDescription&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  } &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Clip buffering started.&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Screen recording has privacy implications. &lt;code&gt;ReplayKit&lt;/code&gt; presents the user with a modal, requesting to record before it starts. If the user denies the request or if the buffering is unable to start, &lt;code&gt;ReplayKit&lt;/code&gt; passes an &lt;code&gt;Error&lt;/code&gt; object to the closure. Unlike other privacy modals, you do not have an opportunity to add your own language to the message. The modal appears as soon as you execute the &lt;code&gt;.startClipBuffering&lt;/code&gt; command, so be sure that the user is not surprised by it. Execute the command at a logical transition in your application. After the user grants permissions, the modal will not appear again unless eight minutes pass before the next call to &lt;code&gt;.startClipBuffering&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;permissions-1&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 250px) 250px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;250&quot; height=&quot;193&quot; src=&quot;https://img.ly/_astro/permissions-1_2qx6ET.webp&quot; srcset=&quot;/_astro/permissions-1_2qx6ET.webp 250w&quot;&gt;&lt;/p&gt;
&lt;p&gt;While the clip buffering runs, at any time, you can save the buffer to a URL on the device. The clip you save can be any duration up to fifteen seconds. If the recorder is unable to write the clip to disk, it will send an error.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; clipURL: URL &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; URL&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;fileURLWithPath&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;NSTemporaryDirectory&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span&gt;appendingPathComponent&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;\(&lt;/span&gt;&lt;span&gt;UUID&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;.mov&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;RPScreenRecorder.&lt;/span&gt;&lt;span&gt;shared&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;exportClip&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;to&lt;/span&gt;&lt;span&gt;: clipURL, &lt;/span&gt;&lt;span&gt;duration&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;TimeInterval&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;)) { err &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if&lt;/span&gt;&lt;span&gt; let&lt;/span&gt;&lt;span&gt; err &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; err {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;An error? &lt;/span&gt;&lt;span&gt;\(err.&lt;/span&gt;&lt;span&gt;localizedDescription&lt;/span&gt;&lt;span&gt; )&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  } &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Clip saved to url &lt;/span&gt;&lt;span&gt;\(clipURL)&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The code above stores a fifteen-second clip at a URL in the user’s temporary directory. The temporary directory gets cleared by the system, but not while the app is running. To ensure that the files are not deleted except by the user, store them in the user’s documents directory instead.&lt;br&gt;
When your app is done collecting video, use &lt;code&gt;.stopClipBuffering&lt;/code&gt; to allow the system to clean up resources and stop the recording.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;RPScreenRecorder.&lt;/span&gt;&lt;span&gt;shared&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;stopClipBuffering&lt;/span&gt;&lt;span&gt; { err &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  if&lt;/span&gt;&lt;span&gt; let&lt;/span&gt;&lt;span&gt; err &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; err {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Error attempting to stop buffering &lt;/span&gt;&lt;span&gt;\(err.&lt;/span&gt;&lt;span&gt;localizedDescription&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  } &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Clip buffering stopped.&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;recording-screen-and-app-audio&quot;&gt;Recording Screen and App Audio&lt;/h2&gt;
&lt;p&gt;Rolling clip buffering runs in the background. You can also allow the user to control when to start and stop screen recording. The API looks similar and is available since iOS 10.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;RPScreenRecorder.&lt;/span&gt;&lt;span&gt;shared&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;startRecording&lt;/span&gt;&lt;span&gt; { err &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  guard&lt;/span&gt;&lt;span&gt; err &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; nil&lt;/span&gt;&lt;span&gt; else&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(err.&lt;/span&gt;&lt;span&gt;debugDescription&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //code to display recording indicator&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As with the rolling clip buffering, the system will display a permissions dialog. If the user denies permission you will get an error and the recording will not start.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;recording-permissions-1&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 250px) 250px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;250&quot; height=&quot;193&quot; src=&quot;https://img.ly/_astro/recording-permissions-1_ZEkXHU.webp&quot; srcset=&quot;/_astro/recording-permissions-1_ZEkXHU.webp 250w&quot;&gt;&lt;/p&gt;
&lt;p&gt;The same eight-minute rule applies as for rolling clip recording. But, since the user has just taken some action to start recording, they should expect to see this modal.&lt;br&gt;
Apple provides a basic view controller for editing and sharing the video.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ReplayKit&lt;/code&gt; passes the &lt;code&gt;RPPreviewViewController&lt;/code&gt; to the &lt;code&gt;.stopRecording&lt;/code&gt; handler.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;RPScreenRecorder.&lt;/span&gt;&lt;span&gt;shared&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;stopRecording&lt;/span&gt;&lt;span&gt; { preview, err &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  guard&lt;/span&gt;&lt;span&gt; let&lt;/span&gt;&lt;span&gt; preview &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; preview &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; { &lt;/span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;no preview window&quot;&lt;/span&gt;&lt;span&gt;); &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //update recording controls&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  preview.modalPresentationStyle &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; .overFullScreen&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  preview.previewControllerDelegate &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; self&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  self&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;present&lt;/span&gt;&lt;span&gt;(preview, &lt;/span&gt;&lt;span&gt;animated&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;preview&lt;/code&gt; object above is the &lt;code&gt;RPPreviewViewController&lt;/code&gt; editor. You can display it as a modal or as a popover depending on your needs. The Apple provided editor will allow the user to save to their camera roll or share the clip after editing.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;apple-editor-1&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 400px) 400px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;400&quot; height=&quot;866&quot; src=&quot;https://img.ly/_astro/apple-editor-1_5tScc.webp&quot; srcset=&quot;/_astro/apple-editor-1_5tScc.webp 400w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Notice in the code above that there is a &lt;code&gt;previewControllerDelegate&lt;/code&gt;. You will need to add some code to the delegate to cleanup and dismiss the editor when the user is done sharing or saving. An example is below.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; previewControllerDidFinish&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt; previewController: RPPreviewViewController) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  previewController.&lt;/span&gt;&lt;span&gt;dismiss&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;animated&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;) { [&lt;/span&gt;&lt;span&gt;weak&lt;/span&gt;&lt;span&gt; self&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //reset the UI and show the recording controls&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;using-many-uiwindow-objects&quot;&gt;Using Many &lt;code&gt;UIWindow&lt;/code&gt; Objects&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;ReplayKit&lt;/code&gt; recording will only capture the main window of your application. When designing for screen recording, you can place any UI elements in a separate &lt;code&gt;UIWindow&lt;/code&gt; object. Although applications typically only have one &lt;code&gt;UIWindow&lt;/code&gt;, iOS allows many windows. A &lt;code&gt;UIWindow&lt;/code&gt; requires a &lt;code&gt;.rootViewController&lt;/code&gt; to provide content. Then use it like any other view in your application.&lt;br&gt;
The UI for this application consists of three &lt;code&gt;UIWindow&lt;/code&gt; objects.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;combined-windows&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 300px) 300px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;300&quot; height=&quot;649&quot; src=&quot;https://img.ly/_astro/combined-windows_ZrRaan.webp&quot; srcset=&quot;/_astro/combined-windows_ZrRaan.webp 300w&quot;&gt;&lt;/p&gt;
&lt;p&gt;Apple places the status bar in a separate window from your application. The recording controls are in a separate window from the main application and will not appear in the screen recording.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;exploded-windows&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 503px) 503px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;503&quot; height=&quot;360&quot; src=&quot;https://img.ly/_astro/exploded-windows_1AjROT.webp&quot; srcset=&quot;/_astro/exploded-windows_1AjROT.webp 503w&quot;&gt;&lt;/p&gt;
&lt;p&gt;To add some recording controls or a recording indicator to your app. Create a new &lt;code&gt;UIWindow&lt;/code&gt; and add it to the same &lt;code&gt;windowScene&lt;/code&gt; as your view.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;controlsWindow &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; UIWindow&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;frame&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;CGRect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;width&lt;/span&gt;&lt;span&gt;: view.frame.width, &lt;/span&gt;&lt;span&gt;height&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;45&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; view.safeAreaInsets.top)) &lt;/span&gt;&lt;span&gt;//1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;controlsWindow&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.windowScene &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; view.window&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.windowScene &lt;/span&gt;&lt;span&gt;//2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;controlsWindow&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;makeKeyAndVisible&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;//3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; recordingIndicator &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; UIButton.&lt;/span&gt;&lt;span&gt;systemButton&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;with&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;UIImage&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;systemName&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;record.circle&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;action&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;#selector&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;recordingToggled&lt;/span&gt;&lt;span&gt;(_:))) &lt;/span&gt;&lt;span&gt;//4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; vc &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; UIViewController&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;controlsWindow&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;.rootViewController &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; vc &lt;/span&gt;&lt;span&gt;//5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;vc.&lt;/span&gt;&lt;span&gt;view&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;addSubview&lt;/span&gt;&lt;span&gt;(recordingIndicator) &lt;/span&gt;&lt;span&gt;//6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;recordingIndicator.center &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; CGPoint&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;: vc.&lt;/span&gt;&lt;span&gt;view&lt;/span&gt;&lt;span&gt;.center.x, &lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;: vc.&lt;/span&gt;&lt;span&gt;view&lt;/span&gt;&lt;span&gt;.center.y &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; 20&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The code above creates the red/blue recording button and banner at the top of the view. It relies on a &lt;code&gt;controlsWindow&lt;/code&gt; variable created at the class level. Here is what it is doing:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Creates a new &lt;code&gt;UIWindow&lt;/code&gt; that is the width of the view and tall enough for the button and the safe area (the area around the notch and status bar)&lt;/li&gt;
&lt;li&gt;Adds the window to the same &lt;code&gt;windowScene&lt;/code&gt; as the current view&lt;/li&gt;
&lt;li&gt;Makes the window visible (&lt;code&gt;UIWindow&lt;/code&gt; objects are &lt;code&gt;hidden&lt;/code&gt; when created) and brings it to the front of the stack of windows&lt;/li&gt;
&lt;li&gt;Creates a button and links it to a method in your class &lt;code&gt;recordingToggled(_:)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Adds a view controller to the window so that there will be some content&lt;/li&gt;
&lt;li&gt;Adds the button to the view controller&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Because the recording indicator and button are in a separate window, they will not appear in any screen recording. Be mindful when showing modal views or alert views, as they may appear behind the extra window. A good strategy is to hide the extra window when showing these views. You can use a similar strategy to hide any other UI elements that should not appear in screen recordings.&lt;/p&gt;
&lt;h2 id=&quot;going-further&quot;&gt;Going Further&lt;/h2&gt;
&lt;p&gt;Though Apple provides a basic editor, you can provide your own editing tools. The examples above showed the rolling clip editor writes the video to the disk. The regular recorder can also write the video to disk. You can stop recording using this code:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; tabindex=&quot;0&quot; data-language=&quot;swift&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt; clipURL: URL &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; URL&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;fileURLWithPath&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;NSTemporaryDirectory&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span&gt;appendingPathComponent&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;\(&lt;/span&gt;&lt;span&gt;UUID&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;.mov&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;RPScreenRecorder.&lt;/span&gt;&lt;span&gt;shared&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;stopRecording&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;withOutput&lt;/span&gt;&lt;span&gt;: clipURL) { err &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  //check for an error and process the url&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This method would replace the &lt;code&gt;.stopRecording { preview, err in&lt;/code&gt; method shown above.&lt;br&gt;
With the video saved, you can use an editor such as the &lt;a href=&quot;https://img.ly/products/video-sdk/&quot;&gt;VideoEditor SDK&lt;/a&gt; to allow your users to add annotations, text and filters to their clips. They can even add audio or combine clips to make a great creation.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;with-editor&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; sizes=&quot;(min-width: 400px) 400px, 100vw&quot; data-astro-image=&quot;constrained&quot; data-astro-image-pos=&quot;center&quot; width=&quot;400&quot; height=&quot;866&quot; src=&quot;https://img.ly/_astro/with-editor_26cWBv.webp&quot; srcset=&quot;/_astro/with-editor_26cWBv.webp 400w&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;In this article, you saw how to capture a rolling screen recording as well as how to capture the screen manually. Further, you saw how using an SDK such as &lt;a href=&quot;https://img.ly/products/video-sdk/&quot;&gt;VideoEditor SDK&lt;/a&gt; allows you to annotate and enhance your clips before sharing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thanks for reading! We hope that you found this tutorial helpful. Feel free to reach out to us on &lt;a href=&quot;https://twitter.com/imgly&quot;&gt;Twitter&lt;/a&gt; with any questions, comments, or suggestions!&lt;/strong&gt;&lt;/p&gt;</content:encoded><dc:creator>Walter</dc:creator><media:content url="https://blog.img.ly/2021/09/screen-record-video-on-app.jpg" medium="image"/><category>iOS App Development</category><category>iOS</category><category>ReplayKit</category><category>Apple</category><category>Mobile App Development</category><category>Video Editing</category><category>How-To</category><category>Tutorial</category></item></channel></rss>