CINXE.COM
Create accessible Single App Mode experiences - WWDC22 - Videos - Apple Developer
<!DOCTYPE html> <html xmlns="https://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta charset="utf-8" /> <meta name="Author" content="Apple Inc." /> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> <link rel="shortcut icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" /> <link rel="mask-icon" href="/apple-logo.svg" color="#333333"> <link rel="stylesheet" href="/assets/styles/global.dist.css?02002514015" type="text/css" /> <link rel="stylesheet" href="/assets/styles/dark-mode.css?17182448067" type="text/css" media="(prefers-color-scheme: dark)" data-color-scheme="dark" /> <link rel="stylesheet" href="/assets/styles/localization.css?39172414191" type="text/css" /> <script src="/assets/scripts/lib/jquery/jquery-3.6.0.min.js?17182448067"></script> <script src="/assets/scripts/settings.js?17182448067"></script> <script src="/assets/scripts/language-locales.js?17182448067"></script> <script src="/assets/scripts/DeveloperBreadcrumbs.js?05182434080"></script> <script async src="/assets/scripts/lib/jquery/jquery.retinate.js?17182448067"></script> <script async src="/assets/scripts/global.js?17182448067"></script> <script async src="/assets/scripts/global-logout.js?17182448067"></script> <link rel="stylesheet" href="https://www.apple.com/wss/fonts?family=SF+Pro&v=2" type="text/css" /> <link rel="stylesheet" href="https://www.apple.com/wss/fonts?family=SF+Pro+Icons&v=1" type="text/css" /> <link rel="stylesheet" href="https://www.apple.com/wss/fonts?family=SF+Mono&v=2" type="text/css" /> <link rel="stylesheet" href="https://www.apple.com/wss/fonts?family=Apple+Icons&v=1" type="text/css" /> <title>Create accessible Single App Mode experiences - WWDC22 - Videos - Apple Developer</title> <meta name="omni_page" content="Create accessible Single App Mode experiences - WWDC22 - Videos" /> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <link type="text/css" rel="stylesheet" href="/videos/styles/videos.css?2"> <link type="text/css" rel="stylesheet" href="/videos/styles/video-overlay.css?2"> <meta name="description" content="Learn how you can provide more control and accessibility to people using your apps in Single App Mode. We'll share how you can use the..."> <meta property="og:url" content="https://developer.apple.com/videos/play/wwdc2022/10152/" /> <meta property="og:title" content="Create accessible Single App Mode experiences - WWDC22 - Videos - Apple Developer" /> <meta property="og:description" content="Learn how you can provide more control and accessibility to people using your apps in Single App Mode. We'll share how you can use the..." /> <meta property="og:site_name" content="Apple Developer" /> <meta property="og:type" content="website" /> <meta property="og:video" content="https://devstreaming-cdn.apple.com/videos/wwdc/2022/10152/3/0694C884-66D5-46B5-BAC6-A6671661A771/cmaf.m3u8" /> <meta property="og:video_secure_url" content="https://devstreaming-cdn.apple.com/videos/wwdc/2022/10152/3/0694C884-66D5-46B5-BAC6-A6671661A771/cmaf.m3u8" /> <meta property="og:video:type" content="vnd.apple.mpegURL" /> <meta property="og:video:width" content="1280" /> <meta property="og:video:height" content="720" /> <meta property="og:image" content="https://devimages-cdn.apple.com/wwdc-services/images/124/6651/6651_wide_250x141_2x.jpg" /> <meta property="og:locale" content="en_US" /> <meta itemprop="datePublished" content="2022-06-10"> <meta itemprop="uploadDate" content="2022-06-10"> <link rel="alternate" href="https://developer.apple.com/videos/play/wwdc2022/10152/" hreflang="en"> <link rel="alternate" href="https://developer.apple.com/kr/videos/play/wwdc2022/10152/" hreflang="ko-KR"> <link rel="alternate" href="https://developer.apple.com/cn/videos/play/wwdc2022/10152/" hreflang="zh-CN"> <link rel="alternate" href="https://developer.apple.com/jp/videos/play/wwdc2022/10152/" hreflang="ja-JP"> <link rel="canonical" href="https://developer.apple.com/videos/play/wwdc2022/10152/" /> </head> <body class="view-play theme-dark"> <script> const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches; if (window.Settings.preferredColorScheme) { const colorTheme = (window.Settings.preferredColorScheme === 'auto') && !prefersDark ? 'light' : (window.Settings.preferredColorScheme === 'light') ? 'light' : 'dark' document.body.setAttribute('data-color-scheme', colorTheme); } else { document.body.setAttribute('data-color-scheme', prefersDark ? 'dark' : 'light'); } </script> <style> /* footer */ html body[data-color-scheme='dark'] #main section.section.section-resources.bg-alt {background-color:var(--fill-tertiary);color:var(--glyph-gray);} html body[data-color-scheme='dark'] .developer-router-links {background-color:var(--fill-tertiary);color:var(--glyph-gray);} html body[data-color-scheme='dark'] .footer {background-color:var(--fill-tertiary);color:var(--glyph-gray-tertiary);} /* body backgrounds */ body[data-color-scheme='dark'].dmf {background-color: #000;} html body[data-color-scheme='dark'].dmf .bg-alt {background-color:var(--fill-tertiary);} html body[data-color-scheme='dark'].dmf .bg-blue {background-color:var(--fill-blue-secondary);} html body[data-color-scheme='dark'].dmf .bg-green-blue {background:linear-gradient(135deg, #65976d 0%, #588ea4 100%)} html body[data-color-scheme='dark'].dmf .bg-yellow {background: linear-gradient(to bottom, var(--fill-tertiary) 0%, var(--fill-tertiary-alt) 100%);} html body[data-color-scheme='dark'].dmf .bg-light {background-color:var(--fill-secondary-alt);} html body[data-color-scheme='dark'].dmf .bg-gradient, html body[data-color-scheme='dark'].dmf .bg-grad {background:linear-gradient(to bottom, var(--dark) 0%, var(--fill-gray-secondary-alt) 100%);} html body[data-color-scheme='dark'].dmf .bg-grad-down {background:linear-gradient(to bottom, var(--dark) 0%, var(--fill-gray-secondary-alt) 100%);} html body[data-color-scheme='dark'].dmf .bg-grad-up {background:linear-gradient(to bottom, var(--fill-gray-secondary-alt) 0%, var(--dark) 100%);} html body[data-color-scheme='dark'].dmf .bg-blue-gradient, html body[data-color-scheme='dark'].dmf .bg-gradient-blue {background:linear-gradient(to bottom, var(--fill-blue-gradient-light) 0%, var(--fill-blue-gradient-dark) 100%);} html body[data-color-scheme='dark'].dmf .bg-blue-gradient-alt {background: linear-gradient(90deg, #061830 0%, #102d48 100%);} /* globalNav */ html body[data-color-scheme='dark'] #ac-globalnav {background: var(--fill-tertiary);} /* localNav */ html body[data-color-scheme='dark'] .localnav.localnav-scrim .localnav-background, html body[data-color-scheme='dark'] .localnav-scrim.localnav.localnav-background { background-color: rgba(29, 29, 31, 0.9); } @supports ((-webkit-backdrop-filter: initial) or (backdrop-filter: initial)) { html body[data-color-scheme='dark'] .localnav.localnav-scrim .localnav-background, html body[data-color-scheme='dark'] .localnav-scrim.localnav.localnav-background { background-color: rgba(29, 29, 31, 0.72); } } </style> <link rel="stylesheet" href="/assets/styles/globalnav.css?55202406207" type="text/css" /> <link rel="stylesheet" href="/assets/styles/suggest-lang.css?17182448067" type="text/css" /> <div id="suggest-lang" class="ribbon hide" lang="en"> <div class="ribbon-content-wrapper"> <div class="ribbon-content row"> <div class="column large-12 large-centered"> <p><a href="#" id="suggest-link" class="ribbon-link more">View in English</a></p> <button id="suggest-closer" class="icon icon-after icon-reset" aria-label="Dismiss language suggestion" tabindex="0"></button> </div> </div> </div> </div> <script src="/assets/scripts/suggest-lang.js?17182448067"></script> <aside id="ac-gn-segmentbar" class="ac-gn-segmentbar" lang="en-US" dir="ltr"> </aside> <input type="checkbox" id="ac-gn-menustate" class="ac-gn-menustate" /> <nav id="ac-globalnav" class="no-js" role="navigation" aria-label="Global" data-hires="false" data-analytics-region="global nav" lang="en-US" dir="ltr" data-www-domain="www.apple.com" data-store-locale="us" data-store-root-path="/us" data-store-api="/[storefront]/shop/bag/status" data-search-locale="en_US" data-search-suggestions-api="/search-services/suggestions/" data-search-defaultlinks-api="/search-services/suggestions/defaultlinks/" data-search-suggestions-enabled="false"> <div class="ac-gn-content"> <ul class="ac-gn-header"> <li class="ac-gn-item ac-gn-menuicon"> <label class="ac-gn-menuicon-label" for="ac-gn-menustate" aria-hidden="true"> <span class="ac-gn-menuicon-bread ac-gn-menuicon-bread-top"> <span class="ac-gn-menuicon-bread-crust ac-gn-menuicon-bread-crust-top"></span> </span> <span class="ac-gn-menuicon-bread ac-gn-menuicon-bread-bottom"> <span class="ac-gn-menuicon-bread-crust ac-gn-menuicon-bread-crust-bottom"></span> </span> </label> <a href="#ac-gn-menustate" role="button" class="ac-gn-menuanchor ac-gn-menuanchor-open" id="ac-gn-menuanchor-open"> <span class="ac-gn-menuanchor-label">Global Nav Open Menu</span> </a> <a href="#" role="button" class="ac-gn-menuanchor ac-gn-menuanchor-close" id="ac-gn-menuanchor-close"> <span class="ac-gn-menuanchor-label">Global Nav Close Menu</span> </a> </li> <li class="ac-gn-item ac-gn-apple"> <a class="ac-gn-link ac-gn-link-apple-developer" href="/" data-analytics-title="appledeveloper home" id="ac-gn-firstfocus-small"> <span class="ac-gn-link-text">Apple Developer</span> </a> </li> </ul> <div class="ac-gn-search-placeholder-container" role="search"> <div class="ac-gn-search ac-gn-search-small"> <a id="ac-gn-link-search-small" class="ac-gn-link" href="/search/" data-analytics-title="search" data-analytics-click="search" data-analytics-intrapage-link aria-label="Search"> <div class="ac-gn-search-placeholder-bar"> <div class="ac-gn-search-placeholder-input"> <div class="ac-gn-search-placeholder-input-text" aria-hidden="true"> <div class="ac-gn-link-search ac-gn-search-placeholder-input-icon"></div> <span class="ac-gn-search-placeholder">Search</span> </div> </div> <div class="ac-gn-searchview-close ac-gn-searchview-close-small ac-gn-search-placeholder-searchview-close"> <span class="ac-gn-searchview-close-cancel" aria-hidden="true">Cancel</span> </div> </div> </a> </div> </div> <ul class="ac-gn-list"> <li class="ac-gn-item ac-gn-apple"> <a class="ac-gn-link ac-gn-link-apple-developer" href="/" data-analytics-title="appledeveloper home" id="ac-gn-firstfocus"> <span class="ac-gn-link-text">Apple Developer</span> </a> </li> <li class="ac-gn-item ac-gn-item-menu ac-gn-news"> <a class="ac-gn-link ac-gn-link-news" href="/news/" data-analytics-title="news"> <span class="ac-gn-link-text">News</span> </a> </li> <li class="ac-gn-item ac-gn-item-menu ac-gn-discover"> <a class="ac-gn-link ac-gn-link-discover" href="/discover/" data-analytics-title="discover"> <span class="ac-gn-link-text">Discover</span> </a> </li> <li class="ac-gn-item ac-gn-item-menu ac-gn-design"> <a class="ac-gn-link ac-gn-link-design" href="/design/" data-analytics-title="design"> <span class="ac-gn-link-text">Design</span> </a> </li> <li class="ac-gn-item ac-gn-item-menu ac-gn-develop"> <a class="ac-gn-link ac-gn-link-develop" href="/develop/" data-analytics-title="develop"> <span class="ac-gn-link-text">Develop</span> </a> </li> <li class="ac-gn-item ac-gn-item-menu ac-gn-distribute"> <a class="ac-gn-link ac-gn-link-distribute" href="/distribute/" data-analytics-title="distribute"> <span class="ac-gn-link-text">Distribute</span> </a> </li> <li class="ac-gn-item ac-gn-item-menu ac-gn-dsupport"> <a class="ac-gn-link ac-gn-link-dsupport" href="/support/" data-analytics-title="dsupport"> <span class="ac-gn-link-text">Support</span> </a> </li> <li class="ac-gn-item ac-gn-item-menu ac-gn-account"> <a class="ac-gn-link ac-gn-link-account" href="/account/" data-analytics-title="account"> <span class="ac-gn-link-text">Account</span> </a> </li> <li class="ac-gn-item ac-gn-item-menu ac-gn-search" role="search"> <a id="ac-gn-link-search" class="ac-gn-link ac-gn-link-search" href="/search/" data-analytics-title="search" data-analytics-click="search" data-analytics-intrapage-link aria-label="Search"></a> </li> </ul> <aside id="ac-gn-searchview" class="ac-gn-searchview" role="search" data-analytics-region="search"> <div class="ac-gn-searchview-content"> <div class="ac-gn-searchview-bar"> <div class="ac-gn-searchview-bar-wrapper"> <form id="ac-gn-searchform" class="ac-gn-searchform" action="/search/" method="get"> <div class="ac-gn-searchform-wrapper"> <input id="ac-gn-searchform-input" class="ac-gn-searchform-input" type="text" name="q" aria-label="Search" placeholder="Search" autocorrect="off" autocapitalize="off" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" aria-owns="quicklinks suggestions" /> <button id="ac-gn-searchform-submit" class="ac-gn-searchform-submit" type="submit" disabled aria-label="Submit Search"></button> <button id="ac-gn-searchform-reset" class="ac-gn-searchform-reset" type="reset" disabled aria-label="Clear Search"> <span class="ac-gn-searchform-reset-background"></span> </button> </div> </form> <button id="ac-gn-searchview-close-small" class="ac-gn-searchview-close ac-gn-searchview-close-small" aria-label="Cancel Search"> <span class="ac-gn-searchview-close-cancel" aria-hidden="true"> Cancel </span> </button> </div> </div> <aside id="ac-gn-searchresults" class="ac-gn-searchresults hidden" data-string-quicklinks="Quick Links" data-string-suggestions="Suggested Searches" data-string-noresults=""> <section class="ac-gn-searchresults-section ac-gn-searchresults-section-defaultlinks"> <div class="ac-gn-searchresults-section-wrapper"> <div class="search-group-checkbox hidden"><input id="group-input" type="checkbox" name="group-filter" checked>Only search within “<span id="group-search-label"></span>”</div> <h3 class="ac-gn-searchresults-header ac-gn-searchresults-animated">Quick Links</h3> <ul class="ac-gn-searchresults-list" id="defaultlinks" role="listbox"> </ul> <span role="status" class="ac-gn-searchresults-count" aria-live="polite">5 Quick Links</span> </div> </section> </aside> </div> <button id="ac-gn-searchview-close" class="ac-gn-searchview-close" aria-label="Cancel Search"> <span class="ac-gn-searchview-close-wrapper"> <span class="ac-gn-searchview-close-left"></span> <span class="ac-gn-searchview-close-right"></span> </span> </button> </aside> </div> </nav> <div class="ac-gn-blur"></div> <div id="ac-gn-curtain" class="ac-gn-curtain"></div> <div id="ac-gn-placeholder" class="ac-nav-placeholder"></div> <script src="/assets/scripts/ac-globalnav.built.js?17182448067"></script> <link rel="stylesheet" href="/assets/styles/search.css?17182448067"> <script src="/assets/scripts/search.js?17182448067"></script> <!-- metrics --> <script> /* RSID: */ var s_account="awdappledeveloper" </script> <script src="/assets/metrics/scripts/analytics.js?072620243"></script> <script> s.pageName= AC && AC.Tracking && AC.Tracking.pageName(); s.channel="www.en.developer" s.channel="www.videos.developer"; /************* DO NOT ALTER ANYTHING BELOW THIS LINE ! **************/ var s_code=s.t();if(s_code)document.write(s_code) </script> <!-- /metrics --> <link rel="stylesheet" property="stylesheet" href="/assets/styles/localnav.css" type="text/css" /> <input type="checkbox" id="localnav-menustate" class="localnav-menustate"/> <nav id="localnav" class="localnav localnav-scrim theme-dark" data-sticky role="navigation"> <div class="localnav-wrapper"> <div class="localnav-background"></div> <div class="localnav-content"> <h2 class="localnav-title"> <a href="/videos/">Videos</a> </h2> <div class="localnav-menu"> <a href="#localnav-menustate" class="localnav-menucta-anchor localnav-menucta-anchor-open" id="localnav-menustate-open"> <span class="localnav-menucta-anchor-label">Open Menu</span> </a> <a href="#" class="localnav-menucta-anchor localnav-menucta-anchor-close" id="localnav-menustate-close"> <span class="localnav-menucta-anchor-label">Close Menu</span> </a> <div class="localnav-menu-tray"> <ul class="localnav-menu-items"> <li class="localnav-menu-item"> <a href="/videos/" class="localnav-menu-link">Collection</a> </li> <li class="localnav-menu-item"> <a href="/videos/topics/" class="localnav-menu-link">Topics</a> </li> <li class="localnav-menu-item"> <a href="/videos/all-videos/" class="localnav-menu-link">All Videos</a> </li> <li class="localnav-menu-item"> <a href="/videos/about/" class="localnav-menu-link">About</a> </li> </ul> </div> <div class="localnav-actions localnav-actions-center"> <div class="localnav-action localnav-action-menucta" aria-hidden="true"> <label for="localnav-menustate" class="localnav-menucta"> <span class="localnav-menucta-chevron"></span> </label> </div> </div> </div> </div> </div> </nav> <label id="localnav-curtain" for="localnav-menustate"></label> <script src="/assets/scripts/ac-localnav.built.js"></script> <script type="text/javascript" src="/assets/scripts/localnav.js"></script> <main id="main" class="main theme-dark" role="main"> <section class="bg-dark"> <section class="grid"> <section class="row"> <section class="column large-10 small-12 padding-top-small large-centered no-padding-bottom"> <!-- back link --> <p class="back-link smaller"> <a class="icon icon-before icon-chevronleft" href="/videos/">More Videos</a> </p> </section> </section> <!-- video player --> <section class="video-wrapper row"> <section class="column large-10 small-12 padding-top-small padding-bottom-small large-centered"> <div class="developer-video-player"> <div id="video-status-overlay" class="developer-video-overlay" style="display: none"> <div class="video-status-content"> <div id="video-status-text"></div> <img class="video-status-icon" id="icon-backward" src="/assets/elements/icons/symbols/gobackward5.svg" style="display: none" /> <img class="video-status-icon" id="icon-forward" src="/assets/elements/icons/symbols/goforward5.svg" style="display: none" /> </div> </div> <video id="video" class="video large-centered" controls="" src="https://devstreaming-cdn.apple.com/videos/wwdc/2022/10152/3/0694C884-66D5-46B5-BAC6-A6671661A771/cmaf.m3u8" data-id="wwdc2022-10152" data-locale="en"></video> </div> <div class="no-video-banner hidden"> <div class="no-video-copy"> <p>Streaming is available in most browsers,<br> and in the Developer app.</p> </div> </span> </div> </section> </section> </section> </section> <section class="grid"> <!-- tab menu --> <section class="tab-menu row divider-bottom"> <section class="column large-10 small-12 padding-top-small padding-bottom-small large-centered"> <ul class="tabs"> <li class="tab" data-supplement-id="details"><a href="#"><span class="smaller">Overview</span></a></li> <li class="tab" data-supplement-id="transcript"><a href="#"><span class="smaller">Transcript</span></a></li> <li class="tab right active" data-supplement-id="search"> <!-- mobile search --> <a href="#"><span><!--icon--></span></a> <!-- desktop search --> <section class="searchbar-wrapper desktop" style="opacity:0;"> <button class="search-icon"></button> <input id="searchDesktop" class="active" type="text" autocomplete="off" placeholder="Search this video…"> </section> </li> <section class="searchbar-wrapper mobile"> <input class="active" type="text" autocomplete="off" placeholder="Search this video…"> </section> </ul> </section> </section> <!-- supplements --> <section class="row"> <section class="column large-10 small-12 large-centered no-padding-top no-padding-bottom"> <ul class="supplements hidden"> <!-- details --> <li class="supplement details " data-supplement-id="details"> <h1>Create accessible Single App Mode experiences</h1> <p>Learn how you can provide more control and accessibility to people using your apps in Single App Mode. We'll share how you can use the UIAccessibility and Automatic Assessment Configuration frameworks to apply these restrictions when needed and enable these accessibility features without ever opening the Settings app. We'll also take you through how you can add custom restrictions within your app to better support the Guided Access feature in iOS, which puts any app into Single App Mode temporarily.</p> <h2>Resources</h2> <ul class="links small"> <li class="document"><a href="https://developer.apple.com/documentation/DeviceManagement/AutonomousSingleAppMode" target="_blank">AutonomousSingleAppMode</a></li> <li class="document"><a href="https://developer.apple.com/documentation/UIKit/UIAccessibility/requestGuidedAccessSession(enabled:completionHandler:)" target="_blank">requestGuidedAccessSession(enabled:completionHandler:)</a></li> <li class="download"> <ul class="options"> <li><a href="https://devstreaming-cdn.apple.com/videos/wwdc/2022/10152/3/0694C884-66D5-46B5-BAC6-A6671661A771/downloads/wwdc2022-10152_hd.mp4?dl=1">HD Video</a></li> <li><a href="https://devstreaming-cdn.apple.com/videos/wwdc/2022/10152/3/0694C884-66D5-46B5-BAC6-A6671661A771/downloads/wwdc2022-10152_sd.mp4?dl=1">SD Video</a></li> </ul> </li> </ul> <div class="divider-top margin-top-small padding-bottom-small"></div> <h2>Related Videos</h2> <h4>WWDC23</h4> <ul class="links small"> <li class="video"> <a href="/videos/play/wwdc2023/10034">Create accessible spatial experiences</a> </li> </ul> <h4>WWDC22</h4> <ul class="links small"> <li class="video"> <a href="/videos/play/wwdc2022/110932">WWDC22 Day 4 recap</a> </li> </ul> </li> <!-- transcript --> <li class="supplement transcript" data-supplement-id="transcript" data-shortcut-base-url="/videos/play/wwdc2022/10152/"> <section> <div class="margin-bottom-small download-transcript"><span id="get-transcript" class="icon icon-before icon-downloadcircle">Download</span></div> <p><span class="sentence"><span data-start="0.0">♪ ♪ </span></span><span class="sentence"><span data-start="9.0">Drew Haas: Hi there. My name is Drew Haas, </span></span><span class="sentence"><span data-start="11.0">and I'm an engineer on the Accessibility team. </span></span><span class="sentence"><span data-start="14.0">I'm here to talk about how to create accessible Single App Mode experiences. </span></span><span class="sentence"><span data-start="19.0">Single App Modes let you as a developer serve your users </span></span><span class="sentence"><span data-start="22.0">in really unique ways by restricting certain behaviors </span></span><span class="sentence"><span data-start="26.0">on iOS and iPadOS devices. </span></span><span class="sentence"><span data-start="28.0">Namely, these modes let you lock the device to a single app. </span></span><span class="sentence"><span data-start="33.0">Depending on the mode, </span></span><span class="sentence"><span data-start="34.0">the restrictions are either initiated by the system </span></span><span class="sentence"><span data-start="37.0">or by your app. </span></span><span class="sentence"><span data-start="39.0">This is great because you get to control the timing between a restricted state </span></span><span class="sentence"><span data-start="43.0">and an unrestricted state. </span></span><span class="sentence"><span data-start="46.0">You're also able to apply additional restrictions on top of single app mode, </span></span><span class="sentence"><span data-start="50.0">like whether auto-lock is enabled or not.</p><p></span></span><span class="sentence"><span data-start="54.0">Let's remember to consider accessibility use cases. </span></span><span class="sentence"><span data-start="57.0">You should make sure people who rely using on accessibility features </span></span><span class="sentence"><span data-start="61.0">have the ability to turn them on </span></span><span class="sentence"><span data-start="63.0">so they can use them, even if the device is restricted. </span></span><span class="sentence"><span data-start="66.0">This ensures your app is inclusive to people using assistive technologies. </span></span><span class="sentence"><span data-start="71.0">I want to talk about some examples of when to use Single App Mode. </span></span><span class="sentence"><span data-start="75.0">Let's say you're developing an app where customers order food or drinks </span></span><span class="sentence"><span data-start="79.0">at a restaurant or event. </span></span><span class="sentence"><span data-start="81.0">Or an app that will be used in a medical office, </span></span><span class="sentence"><span data-start="84.0">where patients are handling a device shared by the medical staff </span></span><span class="sentence"><span data-start="87.0">to fill out their information. </span></span><span class="sentence"><span data-start="89.0">Or even an app that helps facilitate a test for students in a classroom. </span></span><span class="sentence"><span data-start="93.0">These are all scenarios where Single App Mode restrictions </span></span><span class="sentence"><span data-start="96.0">help create a focused environment for the user. </span></span><span class="sentence"><span data-start="100.0">And did you know your app might be used in Single App Mode </span></span><span class="sentence"><span data-start="103.0">even if you didn't write code for it? </span></span><span class="sentence"><span data-start="105.0">That's right, Guided Access is an accessibility feature </span></span><span class="sentence"><span data-start="109.0">that lets users put any app in Single App Mode. </span></span><span class="sentence"><span data-start="113.0">First, I'll talk about Guided Access </span></span><span class="sentence"><span data-start="115.0">and go over some considerations you should have </span></span><span class="sentence"><span data-start="117.0">for when people use your app during this mode. </span></span><span class="sentence"><span data-start="121.0">Next, I'll talk about single app modes that you initiate programmatically </span></span><span class="sentence"><span data-start="124.0">from within your app, by adopting certain APIs and frameworks. </span></span><span class="sentence"><span data-start="128.0">And finally, we provide accessibility API </span></span><span class="sentence"><span data-start="131.0">designed for use specifically during Single App Mode. </span></span><span class="sentence"><span data-start="135.0">Use this API to turn on or off certain accessibility features </span></span><span class="sentence"><span data-start="139.0">to create a seamless and accessible experience. </span></span><span class="sentence"><span data-start="142.0">Let's dive in first with Guided Access. </span></span><span class="sentence"><span data-start="145.0">To start Guided Access, first make sure it's turned on </span></span><span class="sentence"><span data-start="148.0">in accessibility settings, then open the app you want to lock on to. </span></span><span class="sentence"><span data-start="152.0">Triple click the side button to perform the accessibility shortcut. </span></span><span class="sentence"><span data-start="157.0">This shows the guided access workspace, where you configure system restrictions. </span></span><span class="sentence"><span data-start="162.0">Then tap Start to begin.</p><p></span></span><span class="sentence"><span data-start="165.0">Now the device is in a restricted state. </span></span><span class="sentence"><span data-start="168.0">It's locked to the frontmost app, </span></span><span class="sentence"><span data-start="170.0">and the restrictions I configured in the options menu are applied. </span></span><span class="sentence"><span data-start="173.0">This helps creates a guided experience for people with cognitive disabilities. </span></span><span class="sentence"><span data-start="179.0">To exit Guided Access, all you need to do </span></span><span class="sentence"><span data-start="181.0">is perform the accessibility shortcut again. </span></span><span class="sentence"><span data-start="184.0">The options menu lets you restrict touch interaction, display motion, </span></span><span class="sentence"><span data-start="189.0">and the software keyboard, as well as hardware button events, </span></span><span class="sentence"><span data-start="192.0">like the volume buttons, and the sleep/wake button. </span></span><span class="sentence"><span data-start="196.0">Having a controlled environment in this way is especially helpful </span></span><span class="sentence"><span data-start="200.0">for people with cognitive disabilities, </span></span><span class="sentence"><span data-start="201.0">but this feature is also enjoyed by a range of users, </span></span><span class="sentence"><span data-start="204.0">from accessibility users to parents of young kids </span></span><span class="sentence"><span data-start="208.0">who could all benefit from having easy access to these device restrictions. </span></span><span class="sentence"><span data-start="212.0">This is where you come in! </span></span><span class="sentence"><span data-start="214.0">UIAccessibility API lets you create custom restrictions </span></span><span class="sentence"><span data-start="217.0">to tailor the experience of your app during Guided Access. </span></span><span class="sentence"><span data-start="221.0">Use this an opportunity to restrict or adjust areas of your app </span></span><span class="sentence"><span data-start="226.0">where someone with a cognitive disability might feel lost </span></span><span class="sentence"><span data-start="228.0">or overwhelmed with options. </span></span><span class="sentence"><span data-start="230.0">I want to share some design considerations for cognitive accessibility. </span></span><span class="sentence"><span data-start="234.0">These are principles you should follow all the time if possible, </span></span><span class="sentence"><span data-start="237.0">but you should especially follow them in your app during Guided Access. </span></span><span class="sentence"><span data-start="242.0">First is to be forgiving of errors. </span></span><span class="sentence"><span data-start="244.0">Try to mitigate errors before they happen, </span></span><span class="sentence"><span data-start="247.0">by warning users before they perform significant or irreversible actions, </span></span><span class="sentence"><span data-start="251.0">like deleting or modifying account information or payment information. </span></span><span class="sentence"><span data-start="256.0">You should aim to reduce dependence on timing </span></span><span class="sentence"><span data-start="258.0">to act on certain things in your app, </span></span><span class="sentence"><span data-start="260.0">because not everybody processes information at the same speed. </span></span><span class="sentence"><span data-start="264.0">Using timed alerts or automatically performing actions </span></span><span class="sentence"><span data-start="268.0">after a short time-out makes your app harder to use. </span></span><span class="sentence"><span data-start="271.0">And you should always, always, give the user a chance to confirm </span></span><span class="sentence"><span data-start="275.0">before making a payment, </span></span><span class="sentence"><span data-start="276.0">this includes apps that have one-tap purchases. </span></span><span class="sentence"><span data-start="280.0">Designing your app with these considerations promotes independence </span></span><span class="sentence"><span data-start="284.0">for accessibility users. </span></span><span class="sentence"><span data-start="286.0">I want to show you an example. </span></span><span class="sentence"><span data-start="288.0">I'm working on an app called Reading Observatory </span></span><span class="sentence"><span data-start="291.0">which helps people keep track of how much they've read during the week. </span></span><span class="sentence"><span data-start="294.0">The home page of my app shows reading progress and has two buttons: </span></span><span class="sentence"><span data-start="298.0">account settings, and a continue reading button. </span></span><span class="sentence"><span data-start="302.0">I've added a custom restriction for my app that will lock the Account Settings button </span></span><span class="sentence"><span data-start="306.0">while Guided Access is active. </span></span><span class="sentence"><span data-start="308.0">This gives my app a unique experience under this restriction, </span></span><span class="sentence"><span data-start="312.0">to help prevent users from getting lost somewhere else, </span></span><span class="sentence"><span data-start="314.0">like buried in account settings, where they may make unintended changes. </span></span><span class="sentence"><span data-start="319.0">This will also reduce the amount of times someone may get stuck </span></span><span class="sentence"><span data-start="322.0">and need help getting back on track with the primary purpose of my app, </span></span><span class="sentence"><span data-start="325.0">which is reading. </span></span><span class="sentence"><span data-start="327.0">To do this, first conform your AppDelegate </span></span><span class="sentence"><span data-start="330.0">to the UIGuidedAccessRestrictionDelegate protocol. </span></span><span class="sentence"><span data-start="333.0">You need to let Guided Access know about each restriction </span></span><span class="sentence"><span data-start="336.0">by providing an array of identifiers. </span></span><span class="sentence"><span data-start="339.0">I've got just one. </span></span><span class="sentence"><span data-start="341.0">You're also required to give a user-facing title for each, </span></span><span class="sentence"><span data-start="344.0">as well as an optional description if you need to provide additional detail. </span></span><span class="sentence"><span data-start="349.0">These strings will show up in the options menu. </span></span><span class="sentence"><span data-start="352.0">Finally, implement the </span></span><span class="sentence"><span data-start="353.0">guidedAccessRestriction (withIdentifier:didChange:) method </span></span><span class="sentence"><span data-start="356.0">to receive a callback when a restriction is toggled. </span></span><span class="sentence"><span data-start="360.0">This is where your app could post a notification to perform logic </span></span><span class="sentence"><span data-start="364.0">which would accommodate the restriction, </span></span><span class="sentence"><span data-start="366.0">like turning off user interaction for certain buttons </span></span><span class="sentence"><span data-start="369.0">or introducing some of those design principles from earlier.</p><p></span></span><span class="sentence"><span data-start="373.0">Check if a custom restriction is enabled at any time by calling </span></span><span class="sentence"><span data-start="376.0">guidedAccessRestrictionState (forIdentifier:) on UIAccessibility. </span></span><span class="sentence"><span data-start="381.0">All of the system provided restrictions and your custom app-based restrictions </span></span><span class="sentence"><span data-start="385.0">make Guided Access extremely configurable, </span></span><span class="sentence"><span data-start="388.0">which is why it is a fantastic accessibility feature. </span></span><span class="sentence"><span data-start="392.0">Guided Access can be found in Accessibility Settings. </span></span><span class="sentence"><span data-start="396.0">Other Single App Modes are available for you to programmatically enter </span></span><span class="sentence"><span data-start="399.0">a restricted session on device. </span></span><span class="sentence"><span data-start="401.0">They share similarities with Guided Access, but the key difference </span></span><span class="sentence"><span data-start="404.0">is just that: you're programmatically entering this mode. </span></span><span class="sentence"><span data-start="408.0">This means there's plenty to talk about for setting up, </span></span><span class="sentence"><span data-start="411.0">starting, and customizing your Single App Mode session. </span></span><span class="sentence"><span data-start="414.0">Remember each of those scenarios from earlier? </span></span><span class="sentence"><span data-start="417.0">An iPad being used as a restaurant kiosk, </span></span><span class="sentence"><span data-start="420.0">at a medical office, in a testing environment– </span></span><span class="sentence"><span data-start="423.0">single App Modes are the right solution for all of these situations. </span></span><span class="sentence"><span data-start="427.0">Even though each may have slightly different needs, </span></span><span class="sentence"><span data-start="430.0">they all benefit from locking the device to a single app. </span></span><span class="sentence"><span data-start="434.0">This prevents people from swiping to go home, </span></span><span class="sentence"><span data-start="436.0">modifying things in Settings, or even looking something up in Safari. </span></span><span class="sentence"><span data-start="441.0">Let's go through each of these and I'll recommend a Single App Mode </span></span><span class="sentence"><span data-start="445.0">based on the restrictions we'll need.</p><p></span></span><span class="sentence"><span data-start="448.0">The first mode is the most basic, and it's the easiest to deploy. </span></span><span class="sentence"><span data-start="452.0">It's simply called Single App Mode. </span></span><span class="sentence"><span data-start="455.0">This is the right solution for when you have a device </span></span><span class="sentence"><span data-start="457.0">that you intend to stay in a single app pretty much in perpetuity. </span></span><span class="sentence"><span data-start="462.0">It remains locked in-app after reboot, </span></span><span class="sentence"><span data-start="464.0">and there is no manual intervention needed for upkeep. </span></span><span class="sentence"><span data-start="468.0">Great for a low-involvement approach. </span></span><span class="sentence"><span data-start="471.0">A few considerations, though! </span></span><span class="sentence"><span data-start="472.0">The device must be supervised. </span></span><span class="sentence"><span data-start="475.0">Supervision tools let you lock a high volume of devices </span></span><span class="sentence"><span data-start="478.0">into Single App Mode at once, </span></span><span class="sentence"><span data-start="480.0">so this is a very scalable solution if you're working with a lot of devices. </span></span><span class="sentence"><span data-start="484.0">Apple Configurator lets you manage supervised devices in many ways, </span></span><span class="sentence"><span data-start="488.0">including putting them in Single App Mode. </span></span><span class="sentence"><span data-start="491.0">Select a supervised device, then under Advanced, select Start Single App Mode.</p><p></span></span><span class="sentence"><span data-start="499.0">The last thing you need to do is select an app. </span></span><span class="sentence"><span data-start="502.0">Once you do, it will launch automatically, </span></span><span class="sentence"><span data-start="505.0">and lock into the foreground.</p><p></span></span><span class="sentence"><span data-start="508.0">There is no other way to exit this mode. </span></span><span class="sentence"><span data-start="510.0">As I mentioned, it will stay locked to this app even upon reboot </span></span><span class="sentence"><span data-start="514.0">unless you end Single App Mode through your management software.</p><p></span></span><span class="sentence"><span data-start="518.0">Autonomous Single App Mode is better suited for situations </span></span><span class="sentence"><span data-start="521.0">where a restricted state is entered and exited often. </span></span><span class="sentence"><span data-start="525.0">For example, at a medical office where a new patient fills in </span></span><span class="sentence"><span data-start="528.0">their information on an iPad, and then hands it back to the staff. </span></span><span class="sentence"><span data-start="532.0">This means there is manual intervention between restrictions. </span></span><span class="sentence"><span data-start="535.0">Your app gets to do this by itself, </span></span><span class="sentence"><span data-start="537.0">by using a single API method call to get in and out. </span></span><span class="sentence"><span data-start="541.0">Again, considerations– the device must be supervised, </span></span><span class="sentence"><span data-start="545.0">and the app that wants to use this API must be allow listed </span></span><span class="sentence"><span data-start="548.0">on the device's configuration profile, </span></span><span class="sentence"><span data-start="551.0">or the request to lock will fail because it's not privileged. </span></span><span class="sentence"><span data-start="554.0">The all-powerful method is </span></span><span class="sentence"><span data-start="556.0">requestGuidedAccessSession(enabled:complet ionHandler:) on UIAccessibility. </span></span><span class="sentence"><span data-start="561.0">Hey, that looks familiar! Right? </span></span><span class="sentence"><span data-start="563.0">This API taps right into the roots of Guided Access. </span></span><span class="sentence"><span data-start="567.0">You're essentially programmatically entering and exiting this feature </span></span><span class="sentence"><span data-start="570.0">with this code. </span></span><span class="sentence"><span data-start="572.0">Isn't that cool? </span></span><span class="sentence"><span data-start="573.0">That's because Guided Access serves as the foundation </span></span><span class="sentence"><span data-start="576.0">for other single app modes to exist. </span></span><span class="sentence"><span data-start="578.0">Bet you didn't know that! </span></span><span class="sentence"><span data-start="580.0">Let's see how this code might work in action. </span></span><span class="sentence"><span data-start="583.0">I have a method each for entering and exiting this mode </span></span><span class="sentence"><span data-start="586.0">that I'll call when I'm ready. </span></span><span class="sentence"><span data-start="588.0">They're performing different actions like starting a new patient sign-up sheet </span></span><span class="sentence"><span data-start="591.0">when we enter a restricted state </span></span><span class="sentence"><span data-start="593.0">and then bookkeep their information upon exiting. </span></span><span class="sentence"><span data-start="597.0">Of course, you'll want to properly address the result of the completion handler </span></span><span class="sentence"><span data-start="600.0">to know if something goes wrong. </span></span><span class="sentence"><span data-start="602.0">If so, you may want to give an alert to the user </span></span><span class="sentence"><span data-start="604.0">and hold off on continuing the experience forward, so they can try again. </span></span><span class="sentence"><span data-start="608.0">Check if Autonomous Single App Mode is enabled at any time </span></span><span class="sentence"><span data-start="611.0">by calling isGuidedAccessEnabled on UIAccessibility. </span></span><span class="sentence"><span data-start="616.0">Also observe the guidedAccessStatusDidChangeNotification </span></span><span class="sentence"><span data-start="619.0">to trigger any additional code when entering or exiting this mode. </span></span><span class="sentence"><span data-start="623.0">And remember that the app which wants to use this API must </span></span><span class="sentence"><span data-start="626.0">have the proper supervision and management, </span></span><span class="sentence"><span data-start="629.0">including allowlisting the app's bundle ID as an allowed application </span></span><span class="sentence"><span data-start="633.0">for Autonomous Single App Mode. </span></span><span class="sentence"><span data-start="636.0">And finally, assessment mode. </span></span><span class="sentence"><span data-start="638.0">This is the right mode when your app aims to prevent unfair advantages, </span></span><span class="sentence"><span data-start="642.0">by restricting certain features during testing. </span></span><span class="sentence"><span data-start="645.0">Turn off autocorrect, spellcheck, </span></span><span class="sentence"><span data-start="648.0">and single app mode locks to the app </span></span><span class="sentence"><span data-start="650.0">so the test taker can't access outside notes or resources. </span></span><span class="sentence"><span data-start="654.0">Recently these frameworks have been unified for iOS and macOS, </span></span><span class="sentence"><span data-start="658.0">when we introduced the Automatic Assessment Configuration framework! </span></span><span class="sentence"><span data-start="662.0">To use this, the device does not need to be supervised like the previous modes, </span></span><span class="sentence"><span data-start="666.0">but you do need to apply to Apple for an assessment entitlement for your app. </span></span><span class="sentence"><span data-start="670.0">More information about applying for the entitlement can be found </span></span><span class="sentence"><span data-start="673.0">in the developer documentation. </span></span><span class="sentence"><span data-start="675.0">My colleague Josh has a fantastic WWDC session </span></span><span class="sentence"><span data-start="678.0">that explains how to use the Automatic Assessment Configuration framework, </span></span><span class="sentence"><span data-start="682.0">including tons of code examples and documentation resources. </span></span><span class="sentence"><span data-start="685.0">Please go check it out. </span></span><span class="sentence"><span data-start="687.0">Once you know which single app mode solution is right for you, </span></span><span class="sentence"><span data-start="690.0">or if you already have a solution working, </span></span><span class="sentence"><span data-start="693.0">remember to keep in mind that people using assistive technologies do use your apps. </span></span><span class="sentence"><span data-start="697.0">There may be extra steps you need to take to make this experience accessible.</p><p></span></span><span class="sentence"><span data-start="702.0">In our classic example of an iPad being used as a restaurant kiosk, </span></span><span class="sentence"><span data-start="706.0">Let's consider that a blind customer comes by to order. </span></span><span class="sentence"><span data-start="711.0">If the device is plainly locked into Single App Mode, then we have a problem. </span></span><span class="sentence"><span data-start="715.0">You wouldn't be able to open Settings, head to Accessibility, </span></span><span class="sentence"><span data-start="718.0">and turn on VoiceOver for this customer. </span></span><span class="sentence"><span data-start="720.0">So what can you do? </span></span><span class="sentence"><span data-start="723.0">Apple Configurator and other device management software </span></span><span class="sentence"><span data-start="726.0">help you configure options for Single App Mode. </span></span><span class="sentence"><span data-start="730.0">A handful of accessibility features are available for you to have always enabled, </span></span><span class="sentence"><span data-start="735.0">and the Accessibility Shortcut, also known as "triple-click" menu, </span></span><span class="sentence"><span data-start="739.0">is configurable to let users quickly toggle accessibility features </span></span><span class="sentence"><span data-start="743.0">like VoiceOver, Zoom, </span></span><span class="sentence"><span data-start="745.0">Invert Colors, AssistiveTouch, and Voice Control. </span></span><span class="sentence"><span data-start="749.0">When these features are always on, </span></span><span class="sentence"><span data-start="751.0">or when they're assigned to the accessibility shortcut, </span></span><span class="sentence"><span data-start="754.0">you enable people who rely on these technologies </span></span><span class="sentence"><span data-start="756.0">to use them while they navigate your app. </span></span><span class="sentence"><span data-start="759.0">It's pretty easy to set this up, so don't miss your chance to do so.</p><p></span></span><span class="sentence"><span data-start="764.0">But those options have to be configured before entering Single App Mode. </span></span><span class="sentence"><span data-start="768.0">So what about during Single App Mode? </span></span><span class="sentence"><span data-start="771.0">Use API on UIAccessibility to toggle certain accessibility features </span></span><span class="sentence"><span data-start="775.0">directly with code. </span></span><span class="sentence"><span data-start="777.0">It's a great alternative to toggling a feature with the accessibility shortcut, </span></span><span class="sentence"><span data-start="781.0">which is helpful when device is encased in a kiosk enclosure </span></span><span class="sentence"><span data-start="785.0">that blocks off hardware buttons. </span></span><span class="sentence"><span data-start="787.0">We made this API so it's easy for you to turn off accessibility features, </span></span><span class="sentence"><span data-start="791.0">so you can do some housekeeping and reset state between users. </span></span><span class="sentence"><span data-start="796.0">To do this, call configureForGuidedAccess on UIAccessibility. </span></span><span class="sentence"><span data-start="800.0">You must pass in a compatible accessibility feature, </span></span><span class="sentence"><span data-start="803.0">and whether you want it enabled or not. </span></span><span class="sentence"><span data-start="805.0">This works for Zoom, VoiceOver, Invert Colors, </span></span><span class="sentence"><span data-start="809.0">AssistiveTouch, and Grayscale. </span></span><span class="sentence"><span data-start="812.0">So whether your app has custom restrictions for Guided Access </span></span><span class="sentence"><span data-start="816.0">or you build your entire experience around Single App Modes, </span></span><span class="sentence"><span data-start="819.0">it's important to know how to make sure it's accessible. </span></span><span class="sentence"><span data-start="823.0">The wrong kind of restrictions make something less accessible to use, </span></span><span class="sentence"><span data-start="827.0">so always consider the experience of someone with a disability using your app. </span></span><span class="sentence"><span data-start="832.0">I've shown you the APIs you need to create an accessible Single App Mode experience. </span></span><span class="sentence"><span data-start="837.0">Now go make something great, and accessible!</span></span></p> </section> </li> <!-- sample code --> <li class="supplement sample-code" data-supplement-id="sample-code"> <section> <ul class="no-bullet padding-top-small margin-bottom"> </ul> </section> </li> <!-- search --> <li class="supplement search active" data-supplement-id="search"> <section class="transcript-results-summary"> <p class="message smaller lighter"><!-- to be populated --></p> <p class="instructions smaller lighter text-center">Looking for something specific? Enter a topic above and jump straight to the good stuff.</p> <p class="error smaller lighter italic text-center" style="display:none;">An error occurred when submitting your query. Please check your Internet connection and try again.</p> </section> <!-- search results --> <ul class="transcript-results row"> </ul> </li> </ul> </section> </section> </section> <input id="analytics-meta" type="hidden" data-event-name="WWDC22" data-event-id="wwdc2022-10152" data-session-id="10152" data-video-name="Create accessible Single App Mode experiences" data-session-response-id=""> </main> <link rel="stylesheet" href="/assets/styles/footer.dist.css?17182448067"> <footer id="footer" class="footer" role="contentinfo" aria-labelledby="footer-label"> <div class="footer-content"> <h2 class="footer-label" id="footer-label">Developer Footer</h2> <developer-breadcrumbs> <li class="footer-breadcrumbs-item"><a href="/videos/">Videos</a></li> <li class="footer-breadcrumbs-item"><a href="/videos/wwdc2022/">WWDC22</a></li> <li class="footer-breadcrumbs-item">Create accessible Single App Mode experiences</li> </developer-breadcrumbs> <nav class="footer-directory" aria-label="Apple Developer Directory" role="navigation"> <!--googleoff: all--> <div class="footer-directory-column"> <input class="footer-directory-column-section-state" type="checkbox" id="footer-directory-column-section-state-platform" /> <div class="footer-directory-column-section"> <label class="footer-directory-column-section-label" for="footer-directory-column-section-state-platform"> <h3 class="footer-directory-column-section-title">Platforms</h3> </label> <a href="#footer-directory-column-section-state-platform" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-open"> <span class="footer-directory-column-section-anchor-label">Open Menu</span> </a> <a href="#" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-close"> <span class="footer-directory-column-section-anchor-label">Close Menu</span> </a> <ul class="footer-directory-column-section-list"> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/ios/">iOS</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/ipados/">iPadOS</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/macos/">macOS</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/tvos/">tvOS</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/visionos/">visionOS</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/watchos/">watchOS</a></li> </ul> </div> <input class="footer-directory-column-section-state" type="checkbox" id="footer-directory-column-section-state-tools" /> <div class="footer-directory-column-section"> <label class="footer-directory-column-section-label" for="footer-directory-column-section-state-tools"> <h3 class="footer-directory-column-section-title">Tools</h3> </label> <a href="#footer-directory-column-section-state-tools" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-open"> <span class="footer-directory-column-section-anchor-label">Open Menu</span> </a> <a href="#" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-close"> <span class="footer-directory-column-section-anchor-label">Close Menu</span> </a> <ul class="footer-directory-column-section-list"> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/swift/">Swift</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/swiftui/">SwiftUI</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/swift-playground/">Swift Playground</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/testflight/">TestFlight</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/xcode/">Xcode</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/xcode-cloud/">Xcode Cloud</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/sf-symbols/">SF Symbols</a></li> </ul> </div> </div> <div class="footer-directory-column"> <input class="footer-directory-column-section-state" type="checkbox" id="footer-directory-column-section-state-topics" /> <div class="footer-directory-column-section"> <label class="footer-directory-column-section-label" for="footer-directory-column-section-state-topics"> <h3 class="footer-directory-column-section-title">Topics & Technologies</h3> </label> <a href="#footer-directory-column-section-state-topics" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-open"> <span class="footer-directory-column-section-anchor-label">Open Menu</span> </a> <a href="#" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-close"> <span class="footer-directory-column-section-anchor-label">Close Menu</span> </a> <ul class="footer-directory-column-section-list"> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/accessibility/">Accessibility</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/accessories/">Accessories</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/app-extensions/">App Extensions</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/app-store/">App Store</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/audio/">Audio & Video</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/augmented-reality/">Augmented Reality</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/design/">Design</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/distribute/">Distribution</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/education/">Education</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/fonts/">Fonts</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/games/">Games</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/health-fitness/">Health & Fitness</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/in-app-purchase/">In-App Purchase</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/localization/">Localization</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/maps/">Maps & Location</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/machine-learning/">Machine Learning</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="https://opensource.apple.com">Open Source</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/security/">Security</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/safari/">Safari & Web</a></li> </ul> </div> </div> <div class="footer-directory-column"> <input class="footer-directory-column-section-state" type="checkbox" id="footer-directory-column-section-state-resources" /> <div class="footer-directory-column-section"> <label class="footer-directory-column-section-label" for="footer-directory-column-section-state-resources"> <h3 class="footer-directory-column-section-title">Resources</h3> </label> <a href="#footer-directory-column-section-state-resources" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-open"> <span class="footer-directory-column-section-anchor-label">Open Menu</span> </a> <a href="#" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-close"> <span class="footer-directory-column-section-anchor-label">Close Menu</span> </a> <ul class="footer-directory-column-section-list"> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/documentation/">Documentation</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/learn/">Tutorials</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/download/">Downloads</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/forums/">Forums</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/videos/">Videos</a></li> </ul> </div> <input class="footer-directory-column-section-state" type="checkbox" id="footer-directory-column-section-state-support" /> <div class="footer-directory-column-section"> <label class="footer-directory-column-section-label" for="footer-directory-column-section-state-support"> <h3 class="footer-directory-column-section-title">Support</h3> </label> <a href="#footer-directory-column-section-state-support" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-open"> <span class="footer-directory-column-section-anchor-label">Open Menu</span> </a> <a href="#" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-close"> <span class="footer-directory-column-section-anchor-label">Close Menu</span> </a> <ul class="footer-directory-column-section-list"> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/support/articles/">Support Articles</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/contact/">Contact Us</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/bug-reporting/">Bug Reporting</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/system-status/">System Status</a></li> </ul> </div> <input class="footer-directory-column-section-state" type="checkbox" id="footer-directory-column-section-state-account" /> <div class="footer-directory-column-section"> <label class="footer-directory-column-section-label" for="footer-directory-column-section-state-account"> <h3 class="footer-directory-column-section-title">Account</h3> </label> <a href="#footer-directory-column-section-state-account" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-open"> <span class="footer-directory-column-section-anchor-label">Open Menu</span> </a> <a href="#" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-close"> <span class="footer-directory-column-section-anchor-label">Close Menu</span> </a> <ul class="footer-directory-column-section-list"> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/account/">Apple Developer</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="https://appstoreconnect.apple.com/">App Store Connect</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/account/ios/certificate/">Certificates, IDs, & Profiles</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="https://feedbackassistant.apple.com/">Feedback Assistant</a></li> </ul> </div> </div> <div class="footer-directory-column"> <input class="footer-directory-column-section-state" type="checkbox" id="footer-directory-column-section-state-programs" /> <div class="footer-directory-column-section"> <label class="footer-directory-column-section-label" for="footer-directory-column-section-state-programs"> <h3 class="footer-directory-column-section-title">Programs</h3> </label> <a href="#footer-directory-column-section-state-programs" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-open"> <span class="footer-directory-column-section-anchor-label">Open Menu</span> </a> <a href="#" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-close"> <span class="footer-directory-column-section-anchor-label">Close Menu</span> </a> <ul class="footer-directory-column-section-list"> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/programs/">Apple Developer Program</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/programs/enterprise/">Apple Developer Enterprise Program</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/app-store/small-business-program/">App Store Small Business Program</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="https://mfi.apple.com/">MFi Program</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/programs/news-partner/">News Partner Program</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/programs/video-partner/">Video Partner Program</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/security-bounty/">Security Bounty Program</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/programs/security-research-device/">Security Research Device Program</a></li> </ul> </div> <input class="footer-directory-column-section-state" type="checkbox" id="footer-directory-column-section-state-events" /> <div class="footer-directory-column-section"> <label class="footer-directory-column-section-label" for="footer-directory-column-section-state-events"> <h3 class="footer-directory-column-section-title">Events</h3> </label> <a href="#footer-directory-column-section-state-events" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-open"> <span class="footer-directory-column-section-anchor-label">Open Menu</span> </a> <a href="#" class="footer-directory-column-section-anchor footer-directory-column-section-anchor-close"> <span class="footer-directory-column-section-anchor-label">Close Menu</span> </a> <ul class="footer-directory-column-section-list"> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/events/">Meet with Apple</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/events/developer-centers/">Apple Developer Centers</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/app-store/app-store-awards/">App Store Awards</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/design/awards/">Apple Design Awards</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/academies/">Apple Developer Academies</a></li> <li class="footer-directory-column-section-item"><a class="footer-directory-column-section-link" href="/wwdc/">WWDC</a></li> </ul> </div> </div> <!--googleon: all--> </nav> <section class="footer-mini" vocab="http://schema.org/" typeof="Organization"> <div class="footer-mini-news"> <div class="copy"> Get the <a href="https://apps.apple.com/us/app/apple-developer/id640199958">Apple Developer app</a>. </div> <div class="content"> <div class="color-scheme-toggle" role="radiogroup" tabindex="0" aria-label="Select a color scheme preference"> <label data-color-scheme-option="light"> <input type="radio" value="light" autocomplete="off" onchange="window.setPreferredColorScheme(event.target.value)" /> <div class="text">Light</div> </label> <label data-color-scheme-option="dark"> <input type="radio" value="dark" autocomplete="off" onchange="window.setPreferredColorScheme(event.target.value)" /> <div class="text">Dark</div> </label> <label data-color-scheme-option="auto"> <input type="radio" value="auto" autocomplete="off" onchange="window.setPreferredColorScheme(event.target.value)" /> <div class="text">Auto</div> </label> </div> <script async src="/assets/scripts/color-scheme-toggle.js"></script> </div> </div> <link rel="stylesheet" href="/assets/styles/language-dropdown.css?17182448067"> <div class="language-dropdown dropdown-container legacy-form hidden"> <select class="dropdown" aria-label="Language Dropdown"></select> <span class="dropdown-icon icon icon-chevrondown" aria-hidden="true"></span> </div> <script src="/assets/scripts/language-dropdown.js?17182448067"></script> <div class="footer-mini-legal"> <div class="footer-mini-legal-copyright">Copyright © 2025 <a href="https://www.apple.com">Apple Inc.</a> All rights reserved.</div> <div class="footer-mini-legal-links"> <a class="footer-mini-legal-link" href="https://www.apple.com/legal/internet-services/terms/site.html" class="first">Terms of Use</a> <a class="footer-mini-legal-link" href="https://www.apple.com/legal/privacy/">Privacy Policy</a> <a class="footer-mini-legal-link" href="/support/terms/">Agreements and Guidelines</a> </div> </div> </section> </div> </footer> <script src="/assets/scripts/params.js"></script> <script src="/assets/scripts/watchable.js"></script> <script src="/assets/scripts/timeout.js"></script> <script src="/videos/scripts/play/play.js?38162550021"></script> <script src="/videos/scripts/hls/rtc.min.js?59182451067"></script> <script src="/videos/scripts/hls/hls.min.js?25152512021"></script> </body> </html>