CINXE.COM

Firebase iOS Codelab Swift

<!doctype html> <html lang="en" dir="ltr"> <head> <meta name="google-signin-client-id" content="721724668570-nbkv1cfusk7kk4eni4pjvepaus73b13t.apps.googleusercontent.com"> <meta name="google-signin-scope" content="profile email https://www.googleapis.com/auth/developerprofiles https://www.googleapis.com/auth/developerprofiles.award"> <meta property="og:site_name" content="Firebase"> <meta property="og:type" content="website"><meta name="theme-color" content="#a8c7fa"><meta charset="utf-8"> <meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="manifest" href="/_pwa/firebase/manifest.json" crossorigin="use-credentials"> <link rel="preconnect" href="//www.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.googleapis.com" crossorigin> <link rel="preconnect" href="//apis.google.com" crossorigin> <link rel="preconnect" href="//www.google-analytics.com" crossorigin><link rel="stylesheet" href="//fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap"> <link rel="stylesheet" href="//fonts.googleapis.com/css2?family=Material+Icons&family=Material+Symbols+Outlined&display=block"><link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase/css/app.css"> <link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase/css/dark-theme.css" disabled> <link rel="shortcut icon" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase/images/favicon.png"> <link rel="apple-touch-icon" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase/images/touchicon-180.png"><link rel="canonical" href="https://firebase.google.com/codelabs/firebase-ios-swift"><link rel="search" type="application/opensearchdescription+xml" title="Firebase" href="https://firebase.google.com/s/opensearch.xml"> <link rel="alternate" hreflang="en" href="https://firebase.google.com/codelabs/firebase-ios-swift" /><link rel="alternate" hreflang="x-default" href="https://firebase.google.com/codelabs/firebase-ios-swift" /><link rel="alternate" hreflang="ar" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=ar" /><link rel="alternate" hreflang="bn" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=bn" /><link rel="alternate" hreflang="zh-Hans" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=zh-cn" /><link rel="alternate" hreflang="zh-Hant" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=zh-tw" /><link rel="alternate" hreflang="fa" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=fa" /><link rel="alternate" hreflang="fr" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=fr" /><link rel="alternate" hreflang="de" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=de" /><link rel="alternate" hreflang="he" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=he" /><link rel="alternate" hreflang="hi" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=hi" /><link rel="alternate" hreflang="id" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=id" /><link rel="alternate" hreflang="it" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=it" /><link rel="alternate" hreflang="ja" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=ja" /><link rel="alternate" hreflang="ko" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=ko" /><link rel="alternate" hreflang="pl" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=pl" /><link rel="alternate" hreflang="pt-BR" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=pt-br" /><link rel="alternate" hreflang="pt" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=pt" /><link rel="alternate" hreflang="ru" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=ru" /><link rel="alternate" hreflang="es" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=es" /><link rel="alternate" hreflang="es-419" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=es-419" /><link rel="alternate" hreflang="th" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=th" /><link rel="alternate" hreflang="tr" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=tr" /><link rel="alternate" hreflang="vi" href="https://firebase.google.com/codelabs/firebase-ios-swift?hl=vi" /><title>Firebase iOS Codelab Swift</title> <meta property="og:title" content="Firebase iOS Codelab Swift"><meta name="description" content="In this codelab, you’ll learn how to use the Firebase platform on iOS in Swift."> <meta property="og:description" content="In this codelab, you’ll learn how to use the Firebase platform on iOS in Swift."><meta property="og:url" content="https://firebase.google.com/codelabs/firebase-ios-swift"><meta property="og:locale" content="en"> <link rel="stylesheet" href="/extras.css"></head> <body class="" template="codelab" theme="firebase-icy-theme" type="codelab" appearance layout="docs" concierge='closed' display-toc pending> <devsite-progress type="indeterminate" id="app-progress"></devsite-progress> <section class="devsite-wrapper"> <devsite-cookie-notification-bar></devsite-cookie-notification-bar><devsite-header role="banner" keep-tabs-visible> <div class="devsite-header--inner nocontent"> <div class="devsite-top-logo-row-wrapper-wrapper"> <div class="devsite-top-logo-row-wrapper"> <div class="devsite-top-logo-row"> <button type="button" id="devsite-hamburger-menu" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Navigation menu button" visually-hidden aria-label="Open menu"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="firebase" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <source srcset="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase/images/lockup.svg" media="(prefers-color-scheme: dark)" class="devsite-dark-theme" alt="Firebase"> <img src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase/images/lockup.svg" class="devsite-site-logo" alt="Firebase"> </picture> </a> </div> <div class="devsite-top-logo-row-middle"> <div class="devsite-header-upper-tabs"> </div> <devsite-search enable-signin enable-search enable-suggestions enable-query-completion tenant-name="Firebase" > <form class="devsite-search-form" action="https://firebase.google.com/s/results" method="GET"> <div class="devsite-search-container"> <button type="button" search-open class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Open search"></button> <div class="devsite-searchbox"> <input aria-activedescendant="" aria-autocomplete="list" aria-label="Search" aria-expanded="false" aria-haspopup="listbox" autocomplete="off" class="devsite-search-field devsite-search-query" name="q" placeholder="Search" role="combobox" type="text" value="" > <div class="devsite-search-image material-icons" aria-hidden="true"> </div> <div class="devsite-search-shortcut-icon-container" aria-hidden="true"> <kbd class="devsite-search-shortcut-icon">/</kbd> </div> </div> </div> </form> <button type="button" search-close class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Close search"></button> </devsite-search> </div> <devsite-appearance-selector></devsite-appearance-selector> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es" >Español</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt" >Português</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_tw" >中文 – 繁體</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> <a class="devsite-header-link devsite-top-button button gc-analytics-event" href="//console.firebase.google.com" data-category="Site-Wide Custom Events" data-label="Site header link" > Go to console </a> <devsite-user enable-profiles fp-auth id="devsite-user"> <span class="button devsite-top-button" aria-hidden="true" visually-hidden>Sign in</span> </devsite-user> </div> </div> </div> </div> </devsite-header> <devsite-book-nav scrollbars hidden> <div class="devsite-book-nav-filter" hidden> <span class="filter-list-icon material-icons" aria-hidden="true"></span> <input type="text" placeholder="Filter" aria-label="Type to filter" role="searchbox"> <span class="filter-clear-button hidden" data-title="Clear filter" aria-label="Clear filter" role="button" tabindex="0"></span> </div> <nav class="devsite-book-nav devsite-nav nocontent" aria-label="Side menu"> <div class="devsite-mobile-header"> <button type="button" id="devsite-close-nav" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Close navigation" aria-label="Close navigation"> </button> <div class="devsite-product-name-wrapper"> <a href="/" class="devsite-site-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav" track-name="firebase" track-metadata-position="nav" track-metadata-eventDetail="nav"> <picture> <source srcset="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase/images/lockup.svg" media="(prefers-color-scheme: dark)" class="devsite-dark-theme" alt="Firebase"> <img src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase/images/lockup.svg" class="devsite-site-logo" alt="Firebase"> </picture> </a> </div> </div> <div class="devsite-book-nav-wrapper"> <div class="devsite-mobile-nav-top"> <ul class="devsite-nav-list"> <li class="devsite-nav-item"> <a href="//console.firebase.google.com" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Go to console" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Go to console </span> </a> </li> </ul> </div> </div> </nav> </devsite-book-nav> <section id="gc-wrapper"> <main role="main" class="devsite-main-content" > <devsite-content> <article class="devsite-article"><style> body { transition: opacity ease-in 0.2s; } body[unresolved] { opacity: 0; display: block; overflow: hidden; position: relative; } </style> <div class="devsite-article-meta nocontent" role="navigation"> <ul class="devsite-breadcrumb-list" > </ul> </div> <h1 class="devsite-page-title" tabindex="-1"> Firebase iOS Codelab Swift </h1> <devsite-feature-tooltip ack-key="AckCollectionsBookmarkTooltipDismiss" analytics-category="Site-Wide Custom Events" analytics-action-show="Callout Profile displayed" analytics-action-close="Callout Profile dismissed" analytics-label="Create Collection Callout" class="devsite-page-bookmark-tooltip nocontent" dismiss-button="true" id="devsite-collections-dropdown" dismiss-button-text="Dismiss" close-button-text="Got it"> <devsite-bookmark></devsite-bookmark> <span slot="popout-heading"> Stay organized with collections </span> <span slot="popout-contents"> Save and categorize content based on your preferences. </span> </devsite-feature-tooltip> <devsite-toc class="devsite-nav" depth="1" devsite-toc-embedded > </devsite-toc> <div class="devsite-article-body clearfix "> <google-codelab-analytics gaid="UA-49880327-14" ga4id="G-JTFZSJVVVZ"></google-codelab-analytics> <google-codelab codelab-gaid="" codelab-ga4id="" doc-id="191BTya7LJ19Rus4nrN9NtJdheii35ltX3I3SCCM50rw" id="firebase-ios-swift" title="Firebase iOS Codelab Swift" no-tooltip="" environment="web" category="firebase,ios" feedback-link="https://github.com/firebase/codelab-friendlychat-ios/issues" layout="paginated" > <google-codelab-step label="Overview" duration="1" step="0"> <google-codelab-about codelab-title="Firebase iOS Codelab Swift" last-updated="2024-11-01T13:19:31Z" duration="20"> </google-codelab-about> <h2 class="step-title" id="0" data-text="Overview" tabindex="-1"> 1. Overview </h2> <p class="image-container"><img alt="2efe6805ef369641.png" style="width: 252.50px" src="/static/codelabs/firebase-ios-swift/img/2efe6805ef369641.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"></p> <p>Welcome to the Friendly Chat codelab. In this codelab, you&#39;ll learn how to use the Firebase platform to create iOS applications. You will implement a chat client and monitor its performance using Firebase.</p> <h3 class="checklist" is-upgraded id="what-youll-learn" data-text="What you'll learn" tabindex="-1"><strong>What you'll learn</strong></h3> <ul class="checklist"> <li>Allow users to sign in.</li> <li>Sync data using the Firebase Realtime Database.</li> <li>Store binary files in Firebase Storage.</li> </ul> <h3 is-upgraded id="what-youll-need" data-text="What you'll need" tabindex="-1"><strong>What you'll need</strong></h3> <ul> <li>Xcode</li> <li>CocoaPods</li> <li>A test device with iOS 8.0+ or simulator</li> </ul> <google-codelab-survey survey-id="firebase-ios-swift-1"> <h4 id="how-will-you-use-this-tutorial" data-text="How will you use this tutorial?" tabindex="-1">How will you use this tutorial?</h4> <paper-radio-group> <paper-radio-button>Read it through only</paper-radio-button> <paper-radio-button>Read it and complete the exercises</paper-radio-button> </paper-radio-group> <h4 id="how-would-rate-your-experience-with-building-ios-apps" data-text="How would rate your experience with building iOS apps?" tabindex="-1">How would rate your experience with building iOS apps?</h4> <paper-radio-group> <paper-radio-button>Novice</paper-radio-button> <paper-radio-button>Intermediate</paper-radio-button> <paper-radio-button>Proficient</paper-radio-button> </paper-radio-group> </google-codelab-survey> </google-codelab-step> <google-codelab-step label="Get the sample code" duration="1" step="1"> <h2 class="step-title" id="1" data-text="Get the sample code" tabindex="-1"> 2. Get the sample code </h2> <p>Clone the GitHub repository from the command line.</p> <div></div><devsite-code><pre translate="no" dir="ltr" is-upgraded>$ git clone https://github.com/firebase/codelab-friendlychat-ios </pre></devsite-code> <aside class="special"><p>The &#34;friendlychat-ios&#34; repository contains many sample projects. This codelab only uses two:</p> <ul> <li><img alt="android_studio_folder.png" style="width: 20.00px" src="/static/codelabs/firebase-ios-swift/img/a1beacb239657647.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"><strong>ios-starter/swift-starter</strong>—The starting code that you&#39;ll build upon in this codelab.</li> <li><img alt="android_studio_folder.png" style="width: 20.00px" src="/static/codelabs/firebase-ios-swift/img/a1beacb239657647.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"><strong>ios/swift</strong>—The complete code for the finished sample app.</li> </ul> </aside> </google-codelab-step> <google-codelab-step label="Build the starter app" duration="2" step="2"> <h2 class="step-title" id="2" data-text="Build the starter app" tabindex="-1"> 3. Build the starter app </h2> <p class="image-container"><img alt="2f4c98d858c453fe.png" style="width: 227.50px" src="/static/codelabs/firebase-ios-swift/img/2f4c98d858c453fe.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2f4c98d858c453fe_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2f4c98d858c453fe_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2f4c98d858c453fe_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2f4c98d858c453fe_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2f4c98d858c453fe_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2f4c98d858c453fe_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2f4c98d858c453fe_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2f4c98d858c453fe_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2f4c98d858c453fe_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2f4c98d858c453fe_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2f4c98d858c453fe_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"></p> <p>To build the starter app:</p> <ol type="1"> <li>In a terminal window, navigate to the <img alt="android_studio_folder.png" style="width: 20.00px" src="/static/codelabs/firebase-ios-swift/img/a1beacb239657647.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/a1beacb239657647_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"><code translate="no" dir="ltr">ios-starter/swift-starter</code> directory from your sample code download</li> <li>Run <code translate="no" dir="ltr">pod install --repo-update</code></li> <li>Open the FriendlyChatSwift.xcworkspace file to open the project in Xcode.</li> <li>Click the <img alt="98205811bbed9d74.png" style="width: 39.00px" src="/static/codelabs/firebase-ios-swift/img/98205811bbed9d74.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"><strong>Run</strong> button.</li> </ol> <p>You should see the Friendly Chat home screen appear after a few seconds. The UI should appear. However, at this point you cannot sign in, send or receive messages. The app will abort with an exception until you complete the next step.</p> </google-codelab-step> <google-codelab-step label="Create Firebase console Project" duration="1" step="3"> <h2 class="step-title" id="3" data-text="Create Firebase console Project" tabindex="-1"> 4. Create Firebase console Project </h2> <h3 is-upgraded id="create-project" data-text="Create project" tabindex="-1"><strong>Create project</strong></h3> <p>From <a href="https://console.firebase.google.com" target="_blank">Firebase console</a> select <strong>Add Project</strong>.</p> <p>Call the project <code translate="no" dir="ltr">FriendlyChat</code>, then click on <strong>Create Project</strong>.</p> <p class="image-container"><img alt="Screenshot from 2015-11-06 14:13:39.png" style="width: 624.00px" src="/static/codelabs/firebase-ios-swift/img/3304fca44a99c25a.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/3304fca44a99c25a_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/3304fca44a99c25a_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/3304fca44a99c25a_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/3304fca44a99c25a_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/3304fca44a99c25a_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/3304fca44a99c25a_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/3304fca44a99c25a_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/3304fca44a99c25a_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/3304fca44a99c25a_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/3304fca44a99c25a_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/3304fca44a99c25a_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"></p> <h3 is-upgraded id="upgrade-your-firebase-pricing-plan" data-text="Upgrade your Firebase pricing plan" tabindex="-1"><strong>Upgrade your Firebase pricing plan</strong></h3> <p>To use Cloud Storage for Firebase, your Firebase project needs to be on the <a href="/docs/projects/billing/firebase-pricing-plans#blaze-pricing-plan" target="_blank">pay-as-you go (Blaze) pricing plan</a>, which means it&#39;s linked to a <a href="/docs/projects/billing/firebase-pricing-plans#cloud-billing-accounts" target="_blank">Cloud Billing account</a>.</p> <ul> <li>A Cloud Billing account requires a payment method, like a credit card.</li> <li>If you&#39;re new to Firebase and Google Cloud, check if you&#39;re eligible for a <a href="/support/faq#pricing-free-trial" target="_blank">$300 credit and a Free Trial Cloud Billing account</a>.</li> <li>If you&#39;re doing this codelab as part of an event, ask your organizer if there are any Cloud credits available.</li> </ul> <p>To upgrade your project to the Blaze plan, follow these steps:</p> <ol type="1"> <li>In the Firebase console, select to <a href="https://console.firebase.google.com/project/_/overview?purchaseBillingPlan=metered" target="_blank">upgrade your plan</a>.</li> <li>Select the Blaze plan. Follow the on-screen instructions to link a Cloud Billing account to your project.<br>If you needed to create a Cloud Billing account as part of this upgrade, you might need to navigate back to the upgrade flow in the Firebase console to complete the upgrade.</li> </ol> <aside class="special"><p><strong>Note</strong>: You can <a href="https://console.firebase.google.com/project/_/overview?purchaseBillingPlan=metered" target="_blank">downgrade your project to the no-cost (Spark) pricing plan</a> after completing this codelab.</p> </aside> <h3 is-upgraded id="connect-your-ios-app" data-text="Connect your iOS app" tabindex="-1"><strong>Connect your iOS app</strong></h3> <ol type="1"> <li>From the Project Overview screen of your new project, click <strong>Add Firebase to your iOS app</strong>.</li> <li>Enter the bundle ID, as &#34;<code translate="no" dir="ltr">com.google.firebase.codelab.FriendlyChatSwift</code>&#34;.</li> <li>Enter the App Store id as &#34;<code translate="no" dir="ltr">123456</code>&#34;.</li> <li>Click <strong>Register App</strong>.</li> </ol> <h3 is-upgraded id="add-googleservice-info.plist-file-to-your-app" data-text="Add GoogleService-Info.plist file to your app" tabindex="-1"><strong>Add GoogleService-Info.plist file to your app</strong></h3> <p>On the second screen click <strong>Download GoogleService-Info.plist</strong> to download a configuration file that contains all the necessary Firebase metadata for your app. Copy that file to your application and add it to the <em>FriendlyChatSwift</em> target.</p> <p>You can now click the &#34;x&#34; in the upper right corner of the popup to close it – skipping steps 3 and 4 – as you will perform those steps here.</p> <h3 is-upgraded id="heading" data-text="" tabindex="-1"><img alt="19d59efb213ddbdc.png" style="width: 260.00px" src="/static/codelabs/firebase-ios-swift/img/19d59efb213ddbdc.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/19d59efb213ddbdc_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/19d59efb213ddbdc_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/19d59efb213ddbdc_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/19d59efb213ddbdc_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/19d59efb213ddbdc_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/19d59efb213ddbdc_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/19d59efb213ddbdc_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/19d59efb213ddbdc_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/19d59efb213ddbdc_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/19d59efb213ddbdc_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/19d59efb213ddbdc_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"></h3> <h3 is-upgraded id="import-firebase-module" data-text="Import Firebase module" tabindex="-1"><strong>Import Firebase module</strong></h3> <p>Start by making sure the <code translate="no" dir="ltr">Firebase</code> module is imported.</p> <h3 is-upgraded id="appdelegate.swift,-fcviewcontroller.swift" data-text="AppDelegate.swift, FCViewController.swift" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/FriendlyChatSwift/AppDelegate.swift#L19" target="_blank">AppDelegate.swift</a>, <a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/FriendlyChatSwift/FCViewController.swift#L20" target="_blank">FCViewController.swift</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"><span class="devsite-syntax-kd">import</span> <span class="devsite-syntax-nc">Firebase</span> </code></pre></devsite-code> <h3 is-upgraded id="configure-firebase-in-appdelegate" data-text="Configure Firebase in AppDelegate" tabindex="-1">Configure Firebase in AppDelegate</h3> <p>Use the &#34;configure&#34; method in FirebaseApp inside the application:didFinishLaunchingWithOptions function to configure underlying Firebase services from your .plist file.</p> <h3 is-upgraded id="appdelegate.swift" data-text="AppDelegate.swift" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/FriendlyChatSwift/AppDelegate.swift#L28" target="_blank">AppDelegate.swift</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"> <span class="devsite-syntax-kd">func</span> <span class="devsite-syntax-nf">application</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-kc">_</span> <span class="devsite-syntax-n">application</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-bp">UIApplication</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">didFinishLaunchingWithOptions</span> <span class="devsite-syntax-n">launchOptions</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">UIApplicationLaunchOptionsKey</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-nb">Any</span><span class="devsite-syntax-p">]?)</span> <span class="devsite-syntax-o">-</span>&gt; <span class="devsite-syntax-nb">Bool</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-n">FirebaseApp</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">configure</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-n">GIDSignIn</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">sharedInstance</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">delegate</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-kc">self</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-kc">true</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> </google-codelab-step> <google-codelab-step label="Identify Users" duration="5" step="4"> <h2 class="step-title" id="4" data-text="Identify Users" tabindex="-1"> 5. Identify Users </h2> <h3 is-upgraded id="use-rules-to-restrict-to-authenticated-users" data-text="Use Rules To Restrict To Authenticated Users" tabindex="-1"><strong>Use Rules To Restrict To Authenticated Users</strong></h3> <p>We will now add a rule to require authentication before reading or writing any messages. To do this we add the following rules to our messages data object. From within the Database section of <a href="http://console.firebase.google.com" target="_blank">Firebase console</a> select Realtime Database, then click on the Rules tab. Then update the rules so they look like this:</p> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"><span class="devsite-syntax-p">{</span> <span class="devsite-syntax-s">"rules"</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-s">"messages"</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-s">".read"</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-s">"auth != null"</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-s">".write"</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-s">"auth != null"</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> <p>For more information on how this works (including documentation on the &#34;auth&#34; variable) see the Firebase <a href="https://firebase.google.com/docs/database/security/quickstart" target="_blank">security documentation</a>.</p> <h3 is-upgraded id="configure-authentication-apis" data-text="Configure Authentication APIs" tabindex="-1"><strong>Configure Authentication APIs</strong></h3> <p>Before your application can access the Firebase Authentication APIs on behalf of your users, you will have to enable it</p> <ol type="1"> <li>Navigate to the <a href="http://console.firebase.google.com" target="_blank">Firebase console</a> and select your project</li> <li>Select <strong>Authentication</strong></li> <li>Select the <strong>Sign In Method</strong> tab</li> <li>Toggle the <strong>Google</strong> switch to enabled (blue)</li> <li>Press <strong>Save</strong> on the resulting dialog</li> </ol> <p>If you get errors later in this codelab with the message &#34;CONFIGURATION_NOT_FOUND&#34;, come back to this step and double check your work.</p> <h3 is-upgraded id="confirm-firebase-auth-dependency" data-text="Confirm Firebase Auth dependency" tabindex="-1"><strong>Confirm Firebase Auth dependency</strong></h3> <p>Confirm Firebase Auth dependencies exist in the <code translate="no" dir="ltr">Podfile</code> file.</p> <h3 is-upgraded id="podfile" data-text="Podfile" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/Podfile#L7" target="_blank">Podfile</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"><span class="devsite-syntax-n">pod</span> <span class="devsite-syntax-err">'</span><span class="devsite-syntax-n">Firebase</span><span class="devsite-syntax-o">/</span><span class="devsite-syntax-n">Auth</span><span class="devsite-syntax-err">'</span> </code></pre></devsite-code> <h3 is-upgraded id="setup-your-info.plist-for-google-sign-in." data-text="Setup your Info.plist for Google Sign In." tabindex="-1"><strong>Setup your Info.plist for Google Sign In.</strong></h3> <p>You&#39;ll need to add a custom URL scheme to your XCode project.</p> <ol type="1"> <li>Open your project configuration: double-click the project name in the left tree view. Select your app from the TARGETS section, then select the Info tab, and expand the URL Types section.</li> <li>Click the + button, and add a URL scheme for your reversed client ID. To find this value, open the GoogleService-Info.plist configuration file, and look for the REVERSED_CLIENT_ID key. Copy the value of that key, and paste it into the URL Schemes box on the configuration page. Leave the other fields blank.</li> <li>When completed, your config should look something similar to the following (but with your application-specific values):</li> </ol> <p class="image-container"><img alt="1b54d5bd2f4f1448.png" style="width: 624.00px" src="/static/codelabs/firebase-ios-swift/img/1b54d5bd2f4f1448.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/1b54d5bd2f4f1448_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/1b54d5bd2f4f1448_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/1b54d5bd2f4f1448_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/1b54d5bd2f4f1448_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/1b54d5bd2f4f1448_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/1b54d5bd2f4f1448_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/1b54d5bd2f4f1448_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/1b54d5bd2f4f1448_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/1b54d5bd2f4f1448_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/1b54d5bd2f4f1448_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/1b54d5bd2f4f1448_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"></p> <h3 is-upgraded id="set-clientid-for-google-sign-in" data-text="Set clientID for Google Sign In" tabindex="-1"><strong>Set clientID for Google Sign In</strong></h3> <p>After Firebase is configured, we can use the clientID to set up the Google Sign In inside the &#34;didFinishLaunchingWithOptions:&#34; method.</p> <h3 is-upgraded id="appdelegate.swift_1" data-text="AppDelegate.swift" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/FriendlyChatSwift/AppDelegate.swift#L62" target="_blank">AppDelegate.swift</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"> <span class="devsite-syntax-kd">func</span> <span class="devsite-syntax-nf">application</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-kc">_</span> <span class="devsite-syntax-n">application</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-bp">UIApplication</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">didFinishLaunchingWithOptions</span> <span class="devsite-syntax-n">launchOptions</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">UIApplicationLaunchOptionsKey</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-nb">Any</span><span class="devsite-syntax-p">]?)</span> <span class="devsite-syntax-o">-</span>&gt; <span class="devsite-syntax-nb">Bool</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-n">FirebaseApp</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">configure</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-n">GIDSignIn</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">sharedInstance</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">clientID</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">FirebaseApp</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">app</span><span class="devsite-syntax-p">()?.</span><span class="devsite-syntax-n">options</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">clientID</span> <span class="devsite-syntax-n">GIDSignIn</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">sharedInstance</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">delegate</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-kc">self</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-kc">true</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> <h3 is-upgraded id="add-the-sign-in-handler" data-text="Add the sign in handler" tabindex="-1"><strong>Add the sign in handler</strong></h3> <p>Once the result of the Google Sign-In was successful, use the account to authenticate with Firebase.</p> <h3 is-upgraded id="appdelegate.swift_2" data-text="AppDelegate.swift" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/FriendlyChatSwift/AppDelegate.swift#L52-L60" target="_blank">AppDelegate.swift</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"> <span class="devsite-syntax-kd">func</span> <span class="devsite-syntax-nf">sign</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-kc">_</span> <span class="devsite-syntax-n">signIn</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">GIDSignIn</span><span class="devsite-syntax-p">!,</span> <span class="devsite-syntax-n">didSignInFor</span> <span class="devsite-syntax-n">user</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">GIDGoogleUser</span><span class="devsite-syntax-p">!,</span> <span class="devsite-syntax-n">withError</span> <span class="devsite-syntax-n">error</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">Error</span><span class="devsite-syntax-p">?)</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">error</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">error</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-bp">print</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"Error </span><span class="devsite-syntax-si">\(</span><span class="devsite-syntax-n">error</span><span class="devsite-syntax-si">)</span><span class="devsite-syntax-s">"</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-k">guard</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">authentication</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">user</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">authentication</span> <span class="devsite-syntax-k">else</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">credential</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">GoogleAuthProvider</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">credential</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">withIDToken</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">authentication</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">idToken</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">accessToken</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">authentication</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">accessToken</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-n">Auth</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">auth</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">signIn</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">with</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">credential</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">user</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">error</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">in</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">error</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">error</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-bp">print</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"Error </span><span class="devsite-syntax-si">\(</span><span class="devsite-syntax-n">error</span><span class="devsite-syntax-si">)</span><span class="devsite-syntax-s">"</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> <p>Automatically sign in the user. Then add a listener to Firebase Auth, to let the user into the app, after successful sign in. And remove the listener on deinit.</p> <h3 is-upgraded id="signinviewcontroller.swift" data-text="SignInViewController.swift" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/FriendlyChatSwift/SignInViewController.swift#L32-L43" target="_blank">SignInViewController.swift</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"> <span class="devsite-syntax-kr">override</span> <span class="devsite-syntax-kd">func</span> <span class="devsite-syntax-nf">viewDidLoad</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-kc">super</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">viewDidLoad</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-n">GIDSignIn</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">sharedInstance</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">uiDelegate</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-kc">self</span> <span class="devsite-syntax-n">GIDSignIn</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">sharedInstance</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">signInSilently</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-n">handle</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">Auth</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">auth</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">addStateDidChangeListener</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">auth</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">user</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">in</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-n">user</span> <span class="devsite-syntax-o">!=</span> <span class="devsite-syntax-kc">nil</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-n">MeasurementHelper</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">sendLoginEvent</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-kc">self</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">performSegue</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">withIdentifier</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">Constants</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">Segues</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">SignInToFp</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">sender</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-kc">nil</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-kd">deinit</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">handle</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">handle</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-n">Auth</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">auth</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">removeStateDidChangeListener</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">handle</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> <h3 is-upgraded id="sign-out" data-text="Sign Out" tabindex="-1"><strong>Sign Out</strong></h3> <p>Add the Sign out method</p> <h3 is-upgraded id="fcviewcontroller.swift" data-text="FCViewController.swift" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/FriendlyChatSwift/FCViewController.swift#L297-L305" target="_blank">FCViewController.swift</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"> <span class="devsite-syntax-kr">@IBAction</span> <span class="devsite-syntax-kd">func</span> <span class="devsite-syntax-nf">signOut</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-kc">_</span> <span class="devsite-syntax-n">sender</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-bp">UIButton</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">firebaseAuth</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">Auth</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">auth</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-k">do</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">try</span> <span class="devsite-syntax-n">firebaseAuth</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">signOut</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-n">dismiss</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">animated</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-kc">true</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">completion</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-kc">nil</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-k">catch</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">signOutError</span> <span class="devsite-syntax-k">as</span> <span class="devsite-syntax-bp">NSError</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-bp">print</span> <span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"Error signing out: </span><span class="devsite-syntax-si">\(</span><span class="devsite-syntax-n">signOutError</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">localizedDescription</span><span class="devsite-syntax-si">)</span><span class="devsite-syntax-s">"</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> <h3 is-upgraded id="test-reading-messages-as-signed-in-user" data-text="Test Reading Messages as Signed In User" tabindex="-1"><strong>Test Reading Messages as Signed In User</strong></h3> <ol type="1"> <li>Click the <img alt="98205811bbed9d74.png" style="width: 39.00px" src="/static/codelabs/firebase-ios-swift/img/98205811bbed9d74.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"><strong>Run</strong> button.</li> <li>You should be immediately sent to the sign-in screen. Tap the Google Sign-In button.</li> <li>You should then be sent to the messaging screen if everything worked well.</li> </ol> </google-codelab-step> <google-codelab-step label="Activate Realtime Database" duration="5" step="5"> <h2 class="step-title" id="5" data-text="Activate Realtime Database" tabindex="-1"> 6. Activate Realtime Database </h2> <p class="image-container"><img alt="2efe6805ef369641.png" style="width: 252.50px" src="/static/codelabs/firebase-ios-swift/img/2efe6805ef369641.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/2efe6805ef369641_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"></p> <h3 is-upgraded id="import-messages" data-text="Import Messages" tabindex="-1"><strong>Import Messages</strong></h3> <p>In your project in <a href="https://console.firebase.google.com" target="_blank">Firebase console</a> select the <strong>Database</strong> item on the left navigation bar. In the overflow menu of the Database select <strong>Import JSON</strong>. Browse to the <code translate="no" dir="ltr">initial_messages.json</code> file in the friendlychat directory, select it then click the <strong>Import</strong> button. This will replace any data currently in your database. You could also edit the database directly, using the green + and red x to add and remove items.</p> <p class="image-container"><img alt="20ccf4856b715b4c.png" style="width: 292.86px" src="/static/codelabs/firebase-ios-swift/img/20ccf4856b715b4c.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/20ccf4856b715b4c_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/20ccf4856b715b4c_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/20ccf4856b715b4c_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/20ccf4856b715b4c_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/20ccf4856b715b4c_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/20ccf4856b715b4c_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/20ccf4856b715b4c_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/20ccf4856b715b4c_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/20ccf4856b715b4c_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/20ccf4856b715b4c_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/20ccf4856b715b4c_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"></p> <p>After importing your database should look like this:</p> <p class="image-container"><img alt="f3e0367f1c9cd187.png" style="width: 624.00px" src="/static/codelabs/firebase-ios-swift/img/f3e0367f1c9cd187.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f3e0367f1c9cd187_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f3e0367f1c9cd187_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f3e0367f1c9cd187_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f3e0367f1c9cd187_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f3e0367f1c9cd187_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f3e0367f1c9cd187_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f3e0367f1c9cd187_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f3e0367f1c9cd187_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f3e0367f1c9cd187_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f3e0367f1c9cd187_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f3e0367f1c9cd187_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"></p> <h3 is-upgraded id="confirm-firebase-database-dependency" data-text="Confirm Firebase Database Dependency" tabindex="-1"><strong>Confirm Firebase Database Dependency</strong></h3> <p>In the dependencies block of the <code translate="no" dir="ltr">Podfile</code> file, confirm that <code translate="no" dir="ltr">Firebase/Database</code> is included.</p> <h3 is-upgraded id="podfile_1" data-text="Podfile" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/Podfile#L10" target="_blank">Podfile</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"><span class="devsite-syntax-n">pod</span> <span class="devsite-syntax-err">'</span><span class="devsite-syntax-n">Firebase</span><span class="devsite-syntax-o">/</span><span class="devsite-syntax-n">Database</span><span class="devsite-syntax-err">'</span> </code></pre></devsite-code> <h3 is-upgraded id="synchronize-existing-messages" data-text="Synchronize Existing Messages" tabindex="-1"><strong>Synchronize Existing Messages</strong></h3> <p>Add code that synchronizes newly added messages to the app UI.</p> <p>The code you add in this section will:</p> <ul> <li>Initialize the Firebase database and add a listener to handle changes made to the database.</li> <li>Update the <code translate="no" dir="ltr">DataSnapshot</code> so new messages will be shown.</li> </ul> <p>Modify your FCViewController&#39;s &#34;deinit&#34;, &#34;configureDatabase&#34;, and &#34;tableView:cellForRow indexPath:&#34; methods; replace with the code defined below:</p> <h3 is-upgraded id="fcviewcontroller.swift_1" data-text="FCViewController.swift" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/FriendlyChatSwift/FCViewController.swift#L62-L73" target="_blank">FCViewController.swift</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"> <span class="devsite-syntax-kd">deinit</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">refHandle</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">_refHandle</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-kc">self</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">ref</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">child</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"messages"</span><span class="devsite-syntax-p">).</span><span class="devsite-syntax-n">removeObserver</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">withHandle</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">_refHandle</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-kd">func</span> <span class="devsite-syntax-nf">configureDatabase</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-n">ref</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">Database</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">database</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">reference</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-c1">// Listen for new messages in the Firebase database</span> <span class="devsite-syntax-n">_refHandle</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-kc">self</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">ref</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">child</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"messages"</span><span class="devsite-syntax-p">).</span><span class="devsite-syntax-n">observe</span><span class="devsite-syntax-p">(.</span><span class="devsite-syntax-n">childAdded</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">with</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-p">[</span><span class="devsite-syntax-kr">weak</span> <span class="devsite-syntax-kc">self</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">snapshot</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-o">-</span>&gt; <span class="devsite-syntax-nb">Void</span> <span class="devsite-syntax-k">in</span> <span class="devsite-syntax-k">guard</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">strongSelf</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-kc">self</span> <span class="devsite-syntax-k">else</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-n">strongSelf</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">messages</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">append</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">snapshot</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-n">strongSelf</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">clientTable</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">insertRows</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">at</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">IndexPath</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">row</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">strongSelf</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">messages</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-bp">count</span><span class="devsite-syntax-o">-</span><span class="devsite-syntax-mi">1</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">section</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-mi">0</span><span class="devsite-syntax-p">)],</span> <span class="devsite-syntax-n">with</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">automatic</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">})</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-kd">func</span> <span class="devsite-syntax-nf">tableView</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-kc">_</span> <span class="devsite-syntax-n">tableView</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-bp">UITableView</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">cellForRowAt</span> <span class="devsite-syntax-n">indexPath</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">IndexPath</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-o">-</span>&gt; <span class="devsite-syntax-bp">UITableViewCell</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-c1">// Dequeue cell</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">cell</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-kc">self</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">clientTable</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">dequeueReusableCell</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">withIdentifier</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-s">"tableViewCell"</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-k">for</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">indexPath</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-c1">// Unpack message from Firebase DataSnapshot</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">messageSnapshot</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-kc">self</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">messages</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">indexPath</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">row</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-k">guard</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">message</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">messageSnapshot</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">value</span> <span class="devsite-syntax-k">as</span><span class="devsite-syntax-p">?</span> <span class="devsite-syntax-p">[</span><span class="devsite-syntax-nb">String</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-nb">String</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-k">else</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-n">cell</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">name</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">message</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Constants</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">MessageFields</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">name</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-p">??</span> <span class="devsite-syntax-s">""</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">text</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">message</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Constants</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">MessageFields</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">text</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-p">??</span> <span class="devsite-syntax-s">""</span> <span class="devsite-syntax-n">cell</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">textLabel</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">text</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">name</span> <span class="devsite-syntax-o">+</span> <span class="devsite-syntax-s">": "</span> <span class="devsite-syntax-o">+</span> <span class="devsite-syntax-n">text</span> <span class="devsite-syntax-n">cell</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">imageView</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">image</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-bp">UIImage</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">named</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-s">"ic_account_circle"</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">photoURL</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">message</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Constants</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">MessageFields</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">photoURL</span><span class="devsite-syntax-p">],</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">URL</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">URL</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">string</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">photoURL</span><span class="devsite-syntax-p">),</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">data</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-k">try</span><span class="devsite-syntax-p">?</span> <span class="devsite-syntax-n">Data</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">contentsOf</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">URL</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-n">cell</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">imageView</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">image</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-bp">UIImage</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">data</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">data</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-n">cell</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> <h3 is-upgraded id="test-message-sync" data-text="Test Message Sync" tabindex="-1"><strong>Test Message Sync</strong></h3> <ol type="1"> <li>Click the <img alt="98205811bbed9d74.png" style="width: 39.00px" src="/static/codelabs/firebase-ios-swift/img/98205811bbed9d74.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"><strong>Run</strong> button.</li> <li>Click the <strong>Sign in to get started</strong> button to go to the messages window.</li> <li>Add new messages directly in Firebase console by clicking on the green + symbol next to the &#34;messages&#34; entry and adding an object like the following: <img alt="f9876ffc8b316b14.png" style="width: 624.00px" src="/static/codelabs/firebase-ios-swift/img/f9876ffc8b316b14.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f9876ffc8b316b14_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f9876ffc8b316b14_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f9876ffc8b316b14_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f9876ffc8b316b14_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f9876ffc8b316b14_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f9876ffc8b316b14_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f9876ffc8b316b14_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f9876ffc8b316b14_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f9876ffc8b316b14_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f9876ffc8b316b14_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/f9876ffc8b316b14_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"></li> <li>Confirm that they show up in the Friendly-Chat UI.</li> </ol> </google-codelab-step> <google-codelab-step label="Send Messages" duration="0" step="6"> <h2 class="step-title" id="6" data-text="Send Messages" tabindex="-1"> 7. Send Messages </h2> <h3 is-upgraded id="implement-send-message" data-text="Implement Send Message" tabindex="-1"><strong>Implement Send Message</strong></h3> <p>Push values to the database. When you use the push method to add data to Firebase Realtime Database, an automatic ID will be added. These auto generated IDs are sequential, which ensures that new messages will be added in the correct order.</p> <p>Modify your FCViewController&#39;s &#34;sendMessage:&#34; method; replace with the code defined below:</p> <h3 is-upgraded id="fcviewcontroller.swift_2" data-text="FCViewController.swift" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/FriendlyChatSwift/FCViewController.swift#L192-L193" target="_blank">FCViewController.swift</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"> <span class="devsite-syntax-kd">func</span> <span class="devsite-syntax-nf">sendMessage</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">withData</span> <span class="devsite-syntax-n">data</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">[</span><span class="devsite-syntax-nb">String</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-nb">String</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-kd">var</span> <span class="devsite-syntax-nv">mdata</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">data</span> <span class="devsite-syntax-n">mdata</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Constants</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">MessageFields</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">name</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">Auth</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">auth</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">currentUser</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">displayName</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">photoURL</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">Auth</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">auth</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">currentUser</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">photoURL</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-n">mdata</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Constants</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">MessageFields</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">photoURL</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">photoURL</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">absoluteString</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-c1">// Push data to Firebase Database</span> <span class="devsite-syntax-kc">self</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">ref</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">child</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"messages"</span><span class="devsite-syntax-p">).</span><span class="devsite-syntax-n">childByAutoId</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">setValue</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">mdata</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> <h3 is-upgraded id="test-sending-messages" data-text="Test Sending Messages" tabindex="-1"><strong>Test Sending Messages</strong></h3> <ol type="1"> <li>Click the <img alt="98205811bbed9d74.png" style="width: 39.00px" src="/static/codelabs/firebase-ios-swift/img/98205811bbed9d74.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"><strong>Run</strong> button.</li> <li>Click <strong>Sign In</strong> to go to the messages window.</li> <li>Type out a message and hit send. The new message should be visible in the app UI and in the Firebase console.</li> </ol> </google-codelab-step> <google-codelab-step label="Store and Receive images" duration="5" step="7"> <h2 class="step-title" id="7" data-text="Store and Receive images" tabindex="-1"> 8. Store and Receive images </h2> <h3 is-upgraded id="confirm-firebase-storage-dependency" data-text="Confirm Firebase Storage Dependency" tabindex="-1"><strong>Confirm Firebase Storage Dependency</strong></h3> <p>In the dependencies block of the <code translate="no" dir="ltr">Podfile</code>, confirm <code translate="no" dir="ltr">Firebase/Storage</code> is included.</p> <h3 is-upgraded id="podfile_2" data-text="Podfile" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/Podfile#L6" target="_blank">Podfile</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"><span class="devsite-syntax-n">pod</span> <span class="devsite-syntax-err">'</span><span class="devsite-syntax-n">Firebase</span><span class="devsite-syntax-o">/</span><span class="devsite-syntax-n">Storage</span><span class="devsite-syntax-err">'</span> </code></pre></devsite-code> <h3 is-upgraded id="set-up-cloud-storage-for-firebase" data-text="Set up Cloud Storage for Firebase" tabindex="-1"><strong>Set up Cloud Storage for Firebase</strong></h3> <p>Here&#39;s how to set up Cloud Storage for Firebase in your Firebase project:</p> <ol type="1"> <li>In the left-panel of the Firebase console, expand <strong>Build</strong> and then select <a href="https://console.firebase.google.com/project/_/storage" target="_blank"><strong>Storage</strong></a>.</li> <li>Click <strong>Get started</strong>.</li> <li>Select a location for your default Storage bucket.<br>Buckets in <code translate="no" dir="ltr">US-WEST1</code>, <code translate="no" dir="ltr">US-CENTRAL1</code>, and <code translate="no" dir="ltr">US-EAST1</code> can take advantage of the <a href="https://cloud.google.com/storage/pricing#cloud-storage-always-free" target="_blank">&#34;Always Free&#34; tier</a> for Google Cloud Storage. Buckets in all other locations follow <a href="https://cloud.google.com/storage/pricing" target="_blank">Google Cloud Storage pricing and usage</a>.</li> <li>Click <strong>Start in test mode</strong>. Read the disclaimer about the security rules.<br>Later in this codelab, you&#39;ll add security rules to secure your data. <strong>Do </strong><strong><em>not</em></strong><strong> distribute or expose an app publicly without adding Security Rules for your Storage bucket.</strong></li> <li>Click <strong>Create</strong>.</li> </ol> <h3 is-upgraded id="configure-firebasestorage" data-text="Configure FirebaseStorage" tabindex="-1"><strong>Configure FirebaseStorage</strong></h3> <h3 is-upgraded id="fcviewcontroller.swift_3" data-text="FCViewController.swift" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/Podfile#L6" target="_blank">FCViewController.swift</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"> <span class="devsite-syntax-kd">func</span> <span class="devsite-syntax-nf">configureStorage</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-n">storageRef</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">Storage</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">storage</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">reference</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> <h3 is-upgraded id="receive-images-in-existing-messages" data-text="Receive images in existing messages" tabindex="-1"><strong>Receive images in existing messages</strong></h3> <p>Add code that downloads images from Firebase Storage.</p> <p>Modify your FCViewController&#39;s &#34;tableView: cellForRowAt indexPath:&#34; method; replace with the code defined below:</p> <h3 is-upgraded id="fcviewcontroller.swift_4" data-text="FCViewController.swift" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/FriendlyChatSwift/FCViewController.swift#L155-L167" target="_blank">FCViewController.swift</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"> <span class="devsite-syntax-kd">func</span> <span class="devsite-syntax-nf">tableView</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-kc">_</span> <span class="devsite-syntax-n">tableView</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-bp">UITableView</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">cellForRowAt</span> <span class="devsite-syntax-n">indexPath</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">IndexPath</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-o">-</span>&gt; <span class="devsite-syntax-bp">UITableViewCell</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-c1">// Dequeue cell</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">cell</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-kc">self</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">clientTable</span> <span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">dequeueReusableCell</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">withIdentifier</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-s">"tableViewCell"</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-k">for</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">indexPath</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-c1">// Unpack message from Firebase DataSnapshot</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">messageSnapshot</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">DataSnapshot</span><span class="devsite-syntax-p">!</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-kc">self</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">messages</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">indexPath</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">row</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-k">guard</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">message</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">messageSnapshot</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">value</span> <span class="devsite-syntax-k">as</span><span class="devsite-syntax-p">?</span> <span class="devsite-syntax-p">[</span><span class="devsite-syntax-nb">String</span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-nb">String</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-k">else</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-n">cell</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">name</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">message</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Constants</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">MessageFields</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">name</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-p">??</span> <span class="devsite-syntax-s">""</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">imageURL</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">message</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Constants</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">MessageFields</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">imageURL</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-n">imageURL</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">hasPrefix</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"gs://"</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-n">Storage</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">storage</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">reference</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">forURL</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">imageURL</span><span class="devsite-syntax-p">).</span><span class="devsite-syntax-n">getData</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">maxSize</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">INT64_MAX</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">{(</span><span class="devsite-syntax-n">data</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">error</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">in</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">error</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">error</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-bp">print</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"Error downloading: </span><span class="devsite-syntax-si">\(</span><span class="devsite-syntax-n">error</span><span class="devsite-syntax-si">)</span><span class="devsite-syntax-s">"</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-n">DispatchQueue</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">main</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-k">async</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-n">cell</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">imageView</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">image</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-bp">UIImage</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-kd">init</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">data</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">data</span><span class="devsite-syntax-p">!)</span> <span class="devsite-syntax-n">cell</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">setNeedsLayout</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-k">else</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">URL</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">URL</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">string</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">imageURL</span><span class="devsite-syntax-p">),</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">data</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-k">try</span><span class="devsite-syntax-p">?</span> <span class="devsite-syntax-n">Data</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">contentsOf</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">URL</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-n">cell</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">imageView</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">image</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-bp">UIImage</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-kd">init</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">data</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">data</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-n">cell</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">textLabel</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">text</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-s">"sent by: </span><span class="devsite-syntax-si">\(</span><span class="devsite-syntax-n">name</span><span class="devsite-syntax-si">)</span><span class="devsite-syntax-s">"</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-k">else</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">text</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">message</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Constants</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">MessageFields</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">text</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-p">??</span> <span class="devsite-syntax-s">""</span> <span class="devsite-syntax-n">cell</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">textLabel</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">text</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">name</span> <span class="devsite-syntax-o">+</span> <span class="devsite-syntax-s">": "</span> <span class="devsite-syntax-o">+</span> <span class="devsite-syntax-n">text</span> <span class="devsite-syntax-n">cell</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">imageView</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">image</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-bp">UIImage</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">named</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-s">"ic_account_circle"</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">photoURL</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">message</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Constants</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">MessageFields</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">photoURL</span><span class="devsite-syntax-p">],</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">URL</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">URL</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">string</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">photoURL</span><span class="devsite-syntax-p">),</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">data</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-k">try</span><span class="devsite-syntax-p">?</span> <span class="devsite-syntax-n">Data</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">contentsOf</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">URL</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-n">cell</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">imageView</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">image</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-bp">UIImage</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">data</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">data</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-n">cell</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> </google-codelab-step> <google-codelab-step label="Send Image Messages" duration="0" step="8"> <h2 class="step-title" id="8" data-text="Send Image Messages" tabindex="-1"> 9. Send Image Messages </h2> <h3 is-upgraded id="implement-store-and-send-images" data-text="Implement Store and Send Images" tabindex="-1"><strong>Implement Store and Send Images</strong></h3> <p>Upload an image from the user, then sync this image&#39;s storage URL to database so this image is sent inside the message.</p> <p>Modify your FCViewController&#39;s &#34;imagePickerController: didFinishPickingMediaWithInfo:&#34; method; replace with the code defined below:</p> <h3 is-upgraded id="fcviewcontroller.swift_5" data-text="FCViewController.swift" tabindex="-1"><a href="https://github.com/firebase/friendlychat/blob/master/ios/swift/FriendlyChatSwift/FCViewController.swift#L221-L244" target="_blank">FCViewController.swift</a></h3> <div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Swift"><code translate="no" dir="ltr"> <span class="devsite-syntax-kd">func</span> <span class="devsite-syntax-nf">imagePickerController</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-kc">_</span> <span class="devsite-syntax-n">picker</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-bp">UIImagePickerController</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">didFinishPickingMediaWithInfo</span> <span class="devsite-syntax-n">info</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">[</span><span class="devsite-syntax-nb">String</span> <span class="devsite-syntax-p">:</span> <span class="devsite-syntax-nb">Any</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-n">picker</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">dismiss</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">animated</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-kc">true</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">completion</span><span class="devsite-syntax-p">:</span><span class="devsite-syntax-kc">nil</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">guard</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">uid</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">Auth</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">auth</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-n">currentUser</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">uid</span> <span class="devsite-syntax-k">else</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-c1">// if it's a photo from the library, not an image from the camera</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-cp">#available</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-cp">iOS</span> <span class="devsite-syntax-mf">8.0</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-o">*</span><span class="devsite-syntax-p">),</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">referenceURL</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-cp">info</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-cp">UIImagePickerControllerReferenceURL</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-k">as</span><span class="devsite-syntax-p">?</span> <span class="devsite-syntax-cp">URL</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">assets</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-bp">PHAsset</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">fetchAssets</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">withALAssetURLs</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">referenceURL</span><span class="devsite-syntax-p">],</span> <span class="devsite-syntax-n">options</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-kc">nil</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">asset</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">assets</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">firstObject</span> <span class="devsite-syntax-n">asset</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">requestContentEditingInput</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">with</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-kc">nil</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">completionHandler</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-p">[</span><span class="devsite-syntax-kr">weak</span> <span class="devsite-syntax-kc">self</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">contentEditingInput</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">info</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">in</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">imageFile</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">contentEditingInput</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">fullSizeImageURL</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">filePath</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-s">"</span><span class="devsite-syntax-si">\(</span><span class="devsite-syntax-n">uid</span><span class="devsite-syntax-si">)</span><span class="devsite-syntax-s">/</span><span class="devsite-syntax-si">\(</span><span class="devsite-syntax-nb">Int</span><span class="devsite-syntax-si">(</span><span class="devsite-syntax-n">Date</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">timeIntervalSinceReferenceDate</span> <span class="devsite-syntax-o">*</span> <span class="devsite-syntax-mi">1000</span><span class="devsite-syntax-si">))</span><span class="devsite-syntax-s">/</span><span class="devsite-syntax-si">\((</span><span class="devsite-syntax-n">referenceURL</span> <span class="devsite-syntax-k">as</span> <span class="devsite-syntax-nb">AnyObject</span><span class="devsite-syntax-si">)</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">lastPathComponent</span><span class="devsite-syntax-p">!</span><span class="devsite-syntax-si">)</span><span class="devsite-syntax-s">"</span> <span class="devsite-syntax-k">guard</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">strongSelf</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-kc">self</span> <span class="devsite-syntax-k">else</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-n">strongSelf</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">storageRef</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">child</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">filePath</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">putFile</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">from</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">imageFile</span><span class="devsite-syntax-p">!,</span> <span class="devsite-syntax-n">metadata</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-kc">nil</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">metadata</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">error</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">in</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">error</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">error</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">nsError</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">error</span> <span class="devsite-syntax-k">as</span> <span class="devsite-syntax-bp">NSError</span> <span class="devsite-syntax-bp">print</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"Error uploading: </span><span class="devsite-syntax-si">\(</span><span class="devsite-syntax-n">nsError</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">localizedDescription</span><span class="devsite-syntax-si">)</span><span class="devsite-syntax-s">"</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-n">strongSelf</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">sendMessage</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">withData</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Constants</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">MessageFields</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">imageURL</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">strongSelf</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">storageRef</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">child</span><span class="devsite-syntax-p">((</span><span class="devsite-syntax-n">metadata</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">path</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-o">!</span><span class="devsite-syntax-p">).</span><span class="devsite-syntax-n">description</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">})</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-k">else</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">guard</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">image</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">info</span><span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">UIImagePickerControllerOriginalImage</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-k">as</span><span class="devsite-syntax-p">?</span> <span class="devsite-syntax-bp">UIImage</span> <span class="devsite-syntax-k">else</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">imageData</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">UIImageJPEGRepresentation</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">image</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-mf">0.8</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">imagePath</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-s">"</span><span class="devsite-syntax-si">\(</span><span class="devsite-syntax-n">uid</span><span class="devsite-syntax-si">)</span><span class="devsite-syntax-s">/</span><span class="devsite-syntax-si">\(</span><span class="devsite-syntax-nb">Int</span><span class="devsite-syntax-si">(</span><span class="devsite-syntax-n">Date</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">timeIntervalSinceReferenceDate</span> <span class="devsite-syntax-o">*</span> <span class="devsite-syntax-mi">1000</span><span class="devsite-syntax-si">))</span><span class="devsite-syntax-s">.jpg"</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">metadata</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">StorageMetadata</span><span class="devsite-syntax-p">()</span> <span class="devsite-syntax-n">metadata</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">contentType</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-s">"image/jpeg"</span> <span class="devsite-syntax-kc">self</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">storageRef</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">child</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">imagePath</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">putData</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">imageData</span><span class="devsite-syntax-p">!,</span> <span class="devsite-syntax-n">metadata</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">metadata</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-p">[</span><span class="devsite-syntax-kr">weak</span> <span class="devsite-syntax-kc">self</span><span class="devsite-syntax-p">]</span> <span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">metadata</span><span class="devsite-syntax-p">,</span> <span class="devsite-syntax-n">error</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">in</span> <span class="devsite-syntax-k">if</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">error</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-n">error</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-bp">print</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s">"Error uploading: </span><span class="devsite-syntax-si">\(</span><span class="devsite-syntax-n">error</span><span class="devsite-syntax-si">)</span><span class="devsite-syntax-s">"</span><span class="devsite-syntax-p">)</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-k">guard</span> <span class="devsite-syntax-kd">let</span> <span class="devsite-syntax-nv">strongSelf</span> <span class="devsite-syntax-p">=</span> <span class="devsite-syntax-kc">self</span> <span class="devsite-syntax-k">else</span> <span class="devsite-syntax-p">{</span> <span class="devsite-syntax-k">return</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-n">strongSelf</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">sendMessage</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-n">withData</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-p">[</span><span class="devsite-syntax-n">Constants</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">MessageFields</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">imageURL</span><span class="devsite-syntax-p">:</span> <span class="devsite-syntax-n">strongSelf</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">storageRef</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-n">child</span><span class="devsite-syntax-p">((</span><span class="devsite-syntax-n">metadata</span><span class="devsite-syntax-p">?.</span><span class="devsite-syntax-n">path</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-o">!</span><span class="devsite-syntax-p">).</span><span class="devsite-syntax-n">description</span><span class="devsite-syntax-p">])</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> <span class="devsite-syntax-p">}</span> </code></pre></devsite-code> <h3 is-upgraded id="test-sending-and-receiving-image-messages" data-text="Test Sending and Receiving Image Messages" tabindex="-1"><strong>Test Sending and Receiving Image Messages</strong></h3> <ol type="1"> <li>Click the <img alt="98205811bbed9d74.png" style="width: 39.00px" src="/static/codelabs/firebase-ios-swift/img/98205811bbed9d74.png" srcset="https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_36.png 36w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_48.png 48w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_72.png 72w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_96.png 96w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_480.png 480w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_720.png 720w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_856.png 856w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_960.png 960w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_1440.png 1440w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_1920.png 1920w,https://firebase.google.com/static/codelabs/firebase-ios-swift/img/98205811bbed9d74_2880.png 2880w" sizes="(max-width: 840px) 100vw, 856px"><strong>Run</strong> button.</li> <li>Click <strong>Sign In</strong> to go to the messages window.</li> <li>Click &#34;add a photo&#34; icon to pick a photo. The new message with the photo should be visible in the app UI and in the Firebase console.</li> </ol> </google-codelab-step> <google-codelab-step label="Congratulations!" duration="0" step="9"> <h2 class="step-title" id="9" data-text="Congratulations!" tabindex="-1"> 10. Congratulations! </h2> <p>You have used Firebase to easily build a real-time chat application.</p> <h3 class="checklist" is-upgraded id="what-weve-covered" data-text="What we've covered" tabindex="-1"><strong>What we've covered</strong></h3> <ul class="checklist"> <li>Realtime Database</li> <li>Federated Sign In</li> <li>Storage</li> </ul> <h3 is-upgraded id="learn-more" data-text="Learn More" tabindex="-1"><strong>Learn More</strong></h3> <ul> <li><a href="https://firebase.google.com" target="_blank">Firebase.google.com</a></li> </ul> </google-codelab-step> </google-codelab> </div> <div class="devsite-floating-action-buttons"> </div> </article> <devsite-content-footer class="nocontent"> <p>Except as otherwise noted, the content of this page is licensed under the <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 License</a>, and code samples are licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 License</a>. For details, see the <a href="https://developers.google.com/site-policies">Google Developers Site Policies</a>. Java is a registered trademark of Oracle and/or its affiliates.</p> </devsite-content-footer> <devsite-notification > </devsite-notification> <div class="devsite-content-data"> <template class="devsite-content-data-template"> [[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],[],[],[]] </template> </div> </devsite-content> </main> <devsite-footer-promos class="devsite-footer"> </devsite-footer-promos> <devsite-footer-linkboxes class="devsite-footer"> <nav class="devsite-footer-linkboxes nocontent" aria-label="Footer links"> <ul class="devsite-footer-linkboxes-list"> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Learn</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/docs/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Developer guides </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/docs/reference/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > SDK & API reference </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/docs/samples/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Samples </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/docs/libraries/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Libraries </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//github.com/firebase/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > GitHub </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Stay connected</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="//firebase.blog" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Check out the blog </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//www.reddit.com/r/Firebase" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Find us on Reddit </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//x.com/Firebase" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Follow on X </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//www.youtube.com/user/Firebase" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Subscribe on YouTube </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/community/events" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > Attend an event </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Support</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/support/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Contact support </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//stackoverflow.com/questions/tagged/firebase" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Stack Overflow </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//firebase.community/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 3)" > Slack community </a> </li> <li class="devsite-footer-linkbox-item"> <a href="//groups.google.com/forum/#!forum/firebase-talk" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 4)" > Google group </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/support/releases" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 5)" > Release notes </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/brand-guidelines/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 6)" > Brand guidelines </a> </li> <li class="devsite-footer-linkbox-item"> <a href="/support/faq/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 7)" > FAQs </a> </li> </ul> </li> </ul> </nav> </devsite-footer-linkboxes> <devsite-footer-utility class="devsite-footer"> <div class="devsite-footer-utility nocontent"> <nav class="devsite-footer-sites" aria-label="Other Google Developers websites"> <a href="https://developers.google.com/" class="devsite-footer-sites-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Google Developers Link"> <picture> <source srcset="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase/images/lockup-google-for-developers-dark-theme.svg" media="(prefers-color-scheme: none)" class="devsite-dark-theme" loading="lazy" alt="Google Developers"> <img class="devsite-footer-sites-logo" src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase/images/lockup-google-for-developers.svg" loading="lazy" alt="Google Developers"> </picture> </a> <ul class="devsite-footer-sites-list"> <li class="devsite-footer-sites-item"> <a href="//developer.android.com" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Android Link" > Android </a> </li> <li class="devsite-footer-sites-item"> <a href="//developer.chrome.com/home" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Chrome Link" > Chrome </a> </li> <li class="devsite-footer-sites-item"> <a href="//firebase.google.com" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Firebase Link" > Firebase </a> </li> <li class="devsite-footer-sites-item"> <a href="//cloud.google.com" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Google Cloud Platform Link" > Google Cloud Platform </a> </li> <li class="devsite-footer-sites-item"> <a href="//developers.google.com/products/" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer All products Link" > All products </a> </li> </ul> </nav> <nav class="devsite-footer-utility-links" aria-label="Utility links"> <ul class="devsite-footer-utility-list"> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="/terms/" data-category="Site-Wide Custom Events" data-label="Footer Terms link" > Terms </a> </li> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="//policies.google.com/privacy" data-category="Site-Wide Custom Events" data-label="Footer Privacy link" > Privacy </a> </li> <li class="devsite-footer-utility-item glue-cookie-notification-bar-control"> <a class="devsite-footer-utility-link gc-analytics-event" href="#" data-category="Site-Wide Custom Events" data-label="Footer Manage cookies link" aria-hidden="true" > Manage cookies </a> </li> </ul> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es" >Español</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt" >Português</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_tw" >中文 – 繁體</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> </nav> </div> </devsite-footer-utility> <devsite-panel></devsite-panel> <devsite-concierge data-info-panel data-ai-panel > </devsite-concierge> </section></section> <devsite-sitemask></devsite-sitemask> <devsite-snackbar></devsite-snackbar> <devsite-tooltip ></devsite-tooltip> <devsite-heading-link></devsite-heading-link> <devsite-analytics> <script type="application/json" analytics>[]</script> <script type="application/json" tag-management>{&#34;at&#34;: &#34;True&#34;, &#34;ga4&#34;: [], &#34;ga4p&#34;: [], &#34;gtm&#34;: [{&#34;id&#34;: &#34;GTM-N84485&#34;, &#34;purpose&#34;: 0}], &#34;parameters&#34;: {&#34;internalUser&#34;: &#34;False&#34;, &#34;language&#34;: {&#34;machineTranslated&#34;: &#34;False&#34;, &#34;requested&#34;: &#34;en&#34;, &#34;served&#34;: &#34;en&#34;}, &#34;pageType&#34;: &#34;codelab&#34;, &#34;projectName&#34;: null, &#34;signedIn&#34;: &#34;False&#34;, &#34;tenant&#34;: &#34;firebase&#34;, &#34;recommendations&#34;: {&#34;sourcePage&#34;: &#34;&#34;, &#34;sourceType&#34;: 0, &#34;sourceRank&#34;: 0, &#34;sourceIdenticalDescriptions&#34;: 0, &#34;sourceTitleWords&#34;: 0, &#34;sourceDescriptionWords&#34;: 0, &#34;experiment&#34;: &#34;&#34;}, &#34;experiment&#34;: {&#34;ids&#34;: &#34;&#34;}}}</script> </devsite-analytics> <devsite-badger></devsite-badger> <firebase-gtm></firebase-gtm> <firebase-utm></firebase-utm> <script nonce="V5D8j0eY4BLua/QJD3RdtUtbg9rUqK"> (function(d,e,v,s,i,t,E){d['GoogleDevelopersObject']=i; t=e.createElement(v);t.async=1;t.src=s;E=e.getElementsByTagName(v)[0]; E.parentNode.insertBefore(t,E);})(window, document, 'script', 'https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase/js/app_loader.js', '[4,"en",null,"/js/devsite_app_module.js","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase","https://firebase-dot-devsite-v2-prod.appspot.com",1,null,["/_pwa/firebase/manifest.json","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/images/video-placeholder.svg","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase/images/favicon.png","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/firebase/images/lockup.svg","https://fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap"],1,null,[1,6,8,12,14,17,21,25,50,52,63,70,75,76,80,87,91,92,93,97,98,100,101,102,103,104,105,107,108,109,110,112,113,116,117,118,120,122,124,125,126,127,129,130,131,132,133,134,135,136,138,140,141,147,148,149,151,152,156,157,158,159,161,163,164,168,169,170,179,180,182,183,186,191,193,196],"AIzaSyAP-jjEJBzmIyKR4F-3XITp8yM9T1gEEI8","AIzaSyB6xiKGDR5O3Ak2okS4rLkauxGUG7XP0hg","firebase.google.com","AIzaSyAQk0fBONSGUqCNznf6Krs82Ap1-NV6J4o","AIzaSyCCxcqdrZ_7QMeLCRY20bh_SXdAYqy70KY",null,null,null,["TpcFeatures__enable_mirror_tenant_redirects","MiscFeatureFlags__developers_footer_image","MiscFeatureFlags__enable_project_variables","Profiles__enable_completecodelab_endpoint","Significatio__enable_by_tenant","Profiles__enable_developer_profiles_callout","MiscFeatureFlags__enable_dark_theme","Profiles__enable_public_developer_profiles","MiscFeatureFlags__emergency_css","Profiles__enable_complete_playlist_endpoint","Search__enable_dynamic_content_confidential_banner","TpcFeatures__enable_required_headers","Cloud__enable_cloudx_ping","Experiments__reqs_query_experiments","MiscFeatureFlags__enable_firebase_utm","Profiles__enable_profile_collections","BookNav__enable_tenant_cache_key","MiscFeatureFlags__developers_footer_dark_image","Cloud__enable_llm_concierge_chat","Profiles__enable_awarding_url","MiscFeatureFlags__enable_explain_this_code","Cloud__enable_legacy_calculator_redirect","MiscFeatureFlags__enable_view_transitions","Analytics__enable_clearcut_logging","Profiles__enable_dashboard_curated_recommendations","Cloud__enable_free_trial_server_call","Search__enable_suggestions_from_borg","DevPro__enable_developer_subscriptions","CloudShell__cloud_code_overflow_menu","Search__enable_ai_eligibility_checks","Search__enable_ai_search_summaries","Profiles__enable_release_notes_notifications","Search__enable_page_map","Concierge__enable_concierge","Cloud__enable_cloudx_experiment_ids","Profiles__require_profile_eligibility_for_signin","MiscFeatureFlags__enable_variable_operator","Profiles__enable_recognition_badges","Cloud__enable_cloud_shell","Concierge__enable_pushui","Cloud__enable_cloud_dlp_service","Profiles__enable_page_saving","EngEduTelemetry__enable_engedu_telemetry","Cloud__enable_cloud_shell_fte_user_flow","DevPro__enable_cloud_innovators_plus","Cloud__enable_cloud_facet_chat","CloudShell__cloud_shell_button"],null,null,"AIzaSyBLEMok-5suZ67qRPzx0qUtbnLmyT_kCVE","https://developerscontentserving-pa.clients6.google.com","AIzaSyCM4QpTRSqP5qI4Dvjt4OAScIN8sOUlO-k","https://developerscontentsearch-pa.clients6.google.com",1,4,null,"https://developerprofiles-pa.clients6.google.com",[4,"firebase","Firebase","firebase.google.com",null,"firebase-dot-devsite-v2-prod.appspot.com",null,null,[1,1,null,null,null,null,null,null,null,null,null,[1],null,null,null,null,null,null,[1],[1,null,null,[1]],null,null,null,[1,null,1],[1,1,null,null,1]],null,[68,null,null,null,null,null,"/images/lockup.svg","/images/touchicon-180.png",null,null,null,1,1,1,null,null,null,null,null,null,null,2,null,null,null,"/images/lockup.svg",[]],[],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[6,1,20,22,23,29,37],null,[[],[1,1]],[[null,null,null,null,["UA-24532603-9"],["GTM-N84485"],null,null,null,null,[["UA-24532603-9",1]],[["GTM-N84485",1]],1],[[2,5],[17,1],[46,8],[36,4],[16,2]],null,1],null,4],null,"pk_live_5170syrHvgGVmSx9sBrnWtA5luvk9BwnVcvIi7HizpwauFG96WedXsuXh790rtij9AmGllqPtMLfhe2RSwD6Pn38V00uBCydV4m"]') </script> <devsite-a11y-announce></devsite-a11y-announce> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10