Firebase iOS Codelab Swift

1. Overview

2efe6805ef369641.png

Welcome to the Friendly Chat codelab. In this codelab, you'll learn how to use the Firebase platform to create iOS applications. You will implement a chat client and monitor its performance using Firebase.

What you'll learn

  • Allow users to sign in.
  • Sync data using the Firebase Realtime Database.
  • Store binary files in Firebase Storage.

What you'll need

  • Xcode
  • CocoaPods
  • A test device with iOS 8.0+ or simulator

How will you use this tutorial?

Read it through only Read it and complete the exercises

How would rate your experience with building iOS apps?

Novice Intermediate Proficient

2. Get the sample code

Clone the GitHub repository from the command line.

$ git clone https://github.com/firebase/codelab-friendlychat-ios

3. Build the starter app

2f4c98d858c453fe.png

To build the starter app:

  1. In a terminal window, navigate to theandroid_studio_folder.png ios-starter/swift-starter directory from your sample code download
  2. Run pod install --repo-update
  3. Open the FriendlyChatSwift.xcworkspace file to open the project in Xcode.
  4. Click the98205811bbed9d74.png Runbutton.

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.

4. Create Firebase console Project

Create project

From Firebase console select Add Project.

Call the project FriendlyChat , then click on Create Project.

Screenshot from 2015-11-06 14:13:39.png

Upgrade your Firebase pricing plan

To use Cloud Storage for Firebase, your Firebase project needs to be on the pay-as-you go (Blaze) pricing plan , which means it's linked to a Cloud Billing account .

  • A Cloud Billing account requires a payment method, like a credit card.
  • If you're new to Firebase and Google Cloud, check if you're eligible for a $300 credit and a Free Trial Cloud Billing account .
  • If you're doing this codelab as part of an event, ask your organizer if there are any Cloud credits available.

To upgrade your project to the Blaze plan, follow these steps:

  1. In the Firebase console, select to upgrade your plan .
  2. Select the Blaze plan. Follow the on-screen instructions to link a Cloud Billing account to your project.
    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.

Connect your iOS app

  1. From the Project Overview screen of your new project, click Add Firebase to your iOS app.
  2. Enter the bundle ID, as " com.google.firebase.codelab.FriendlyChatSwift ".
  3. Enter the App Store id as " 123456 ".
  4. Click Register App.

Add GoogleService-Info.plist file to your app

On the second screen click Download GoogleService-Info.plistto 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 FriendlyChatSwift target.

You can now click the "x" in the upper right corner of the popup to close it – skipping steps 3 and 4 – as you will perform those steps here.

19d59efb213ddbdc.png

Import Firebase module

Start by making sure the Firebase module is imported.

AppDelegate.swift , FCViewController.swift

  import 
  
 Firebase 
 

Configure Firebase in AppDelegate

Use the "configure" method in FirebaseApp inside the application:didFinishLaunchingWithOptions function to configure underlying Firebase services from your .plist file.

AppDelegate.swift

   
 func 
  
 application 
 ( 
 _ 
  
 application 
 : 
  
 UIApplication 
 , 
  
 didFinishLaunchingWithOptions 
  
 launchOptions 
 : 
  
 [ 
 UIApplicationLaunchOptionsKey 
 : 
  
 Any 
 ]?) 
  
 - 
>  
 Bool 
  
 { 
  
 FirebaseApp 
 . 
 configure 
 () 
  
 GIDSignIn 
 . 
 sharedInstance 
 (). 
 delegate 
  
 = 
  
 self 
  
 return 
  
 true 
 } 
 

5. Identify Users

Use Rules To Restrict To Authenticated Users

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 Firebase console select Realtime Database, then click on the Rules tab. Then update the rules so they look like this:

  { 
  
 "rules" 
 : 
  
 { 
  
 "messages" 
 : 
  
 { 
  
 ".read" 
 : 
  
 "auth != null" 
 , 
  
 ".write" 
 : 
  
 "auth != null" 
  
 } 
  
 } 
 } 
 

For more information on how this works (including documentation on the "auth" variable) see the Firebase security documentation .

Configure Authentication APIs

Before your application can access the Firebase Authentication APIs on behalf of your users, you will have to enable it

  1. Navigate to the Firebase console and select your project
  2. Select Authentication
  3. Select the Sign In Methodtab
  4. Toggle the Googleswitch to enabled (blue)
  5. Press Saveon the resulting dialog

If you get errors later in this codelab with the message "CONFIGURATION_NOT_FOUND", come back to this step and double check your work.

Confirm Firebase Auth dependency

Confirm Firebase Auth dependencies exist in the Podfile file.

Podfile

  pod 
  
 ' 
 Firebase 
 / 
 Auth 
 ' 
 

Setup your Info.plist for Google Sign In.

You'll need to add a custom URL scheme to your XCode project.

  1. 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.
  2. 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.
  3. When completed, your config should look something similar to the following (but with your application-specific values):

1b54d5bd2f4f1448.png

After Firebase is configured, we can use the clientID to set up the Google Sign In inside the "didFinishLaunchingWithOptions:" method.

AppDelegate.swift

   
 func 
  
 application 
 ( 
 _ 
  
 application 
 : 
  
 UIApplication 
 , 
  
 didFinishLaunchingWithOptions 
  
 launchOptions 
 : 
  
 [ 
 UIApplicationLaunchOptionsKey 
 : 
  
 Any 
 ]?) 
  
 - 
>  
 Bool 
  
 { 
  
 FirebaseApp 
 . 
 configure 
 () 
  
 GIDSignIn 
 . 
 sharedInstance 
 (). 
 clientID 
  
 = 
  
 FirebaseApp 
 . 
 app 
 ()?. 
 options 
 . 
 clientID 
  
 GIDSignIn 
 . 
 sharedInstance 
 (). 
 delegate 
  
 = 
  
 self 
  
 return 
  
 true 
 } 
 

Once the result of the Google Sign-In was successful, use the account to authenticate with Firebase.

AppDelegate.swift

   
 func 
  
 sign 
 ( 
 _ 
  
 signIn 
 : 
  
 GIDSignIn 
 !, 
  
 didSignInFor 
  
 user 
 : 
  
 GIDGoogleUser 
 !, 
  
 withError 
  
 error 
 : 
  
 Error 
 ?) 
  
 { 
  
 if 
  
 let 
  
 error 
  
 = 
  
 error 
  
 { 
  
 print 
 ( 
 "Error 
 \( 
 error 
 ) 
 " 
 ) 
  
 return 
  
 } 
  
 guard 
  
 let 
  
 authentication 
  
 = 
  
 user 
 . 
 authentication 
  
 else 
  
 { 
  
 return 
  
 } 
  
 let 
  
 credential 
  
 = 
  
 GoogleAuthProvider 
 . 
 credential 
 ( 
 withIDToken 
 : 
  
 authentication 
 . 
 idToken 
 , 
  
 accessToken 
 : 
  
 authentication 
 . 
 accessToken 
 ) 
  
 Auth 
 . 
 auth 
 (). 
 signIn 
 ( 
 with 
 : 
  
 credential 
 ) 
  
 { 
  
 ( 
 user 
 , 
  
 error 
 ) 
  
 in 
  
 if 
  
 let 
  
 error 
  
 = 
  
 error 
  
 { 
  
 print 
 ( 
 "Error 
 \( 
 error 
 ) 
 " 
 ) 
  
 return 
  
 } 
  
 } 
  
 } 
 

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.

SignInViewController.swift

   
 override 
  
 func 
  
 viewDidLoad 
 () 
  
 { 
  
 super 
 . 
 viewDidLoad 
 () 
  
 GIDSignIn 
 . 
 sharedInstance 
 (). 
 uiDelegate 
  
 = 
  
 self 
  
 GIDSignIn 
 . 
 sharedInstance 
 (). 
 signInSilently 
 () 
  
 handle 
  
 = 
  
 Auth 
 . 
 auth 
 (). 
 addStateDidChangeListener 
 () 
  
 { 
  
 ( 
 auth 
 , 
  
 user 
 ) 
  
 in 
  
 if 
  
 user 
  
 != 
  
 nil 
  
 { 
  
 MeasurementHelper 
 . 
 sendLoginEvent 
 () 
  
 self 
 . 
 performSegue 
 ( 
 withIdentifier 
 : 
  
 Constants 
 . 
 Segues 
 . 
 SignInToFp 
 , 
  
 sender 
 : 
  
 nil 
 ) 
  
 } 
  
 } 
  
 } 
  
 deinit 
  
 { 
  
 if 
  
 let 
  
 handle 
  
 = 
  
 handle 
  
 { 
  
 Auth 
 . 
 auth 
 (). 
 removeStateDidChangeListener 
 ( 
 handle 
 ) 
  
 } 
  
 } 
 

Sign Out

Add the Sign out method

FCViewController.swift

   
 @IBAction 
  
 func 
  
 signOut 
 ( 
 _ 
  
 sender 
 : 
  
 UIButton 
 ) 
  
 { 
  
 let 
  
 firebaseAuth 
  
 = 
  
 Auth 
 . 
 auth 
 () 
  
 do 
  
 { 
  
 try 
  
 firebaseAuth 
 . 
 signOut 
 () 
  
 dismiss 
 ( 
 animated 
 : 
  
 true 
 , 
  
 completion 
 : 
  
 nil 
 ) 
  
 } 
  
 catch 
  
 let 
  
 signOutError 
  
 as 
  
 NSError 
  
 { 
  
 print 
  
 ( 
 "Error signing out: 
 \( 
 signOutError 
 . 
 localizedDescription 
 ) 
 " 
 ) 
  
 } 
  
 } 
 

Test Reading Messages as Signed In User

  1. Click the98205811bbed9d74.png Runbutton.
  2. You should be immediately sent to the sign-in screen. Tap the Google Sign-In button.
  3. You should then be sent to the messaging screen if everything worked well.

6. Activate Realtime Database

2efe6805ef369641.png

Import Messages

In your project in Firebase console select the Databaseitem on the left navigation bar. In the overflow menu of the Database select Import JSON. Browse to the initial_messages.json file in the friendlychat directory, select it then click the Importbutton. 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.

20ccf4856b715b4c.png

After importing your database should look like this:

f3e0367f1c9cd187.png

Confirm Firebase Database Dependency

In the dependencies block of the Podfile file, confirm that Firebase/Database is included.

Podfile

  pod 
  
 ' 
 Firebase 
 / 
 Database 
 ' 
 

Synchronize Existing Messages

Add code that synchronizes newly added messages to the app UI.

The code you add in this section will:

  • Initialize the Firebase database and add a listener to handle changes made to the database.
  • Update the DataSnapshot so new messages will be shown.

Modify your FCViewController's "deinit", "configureDatabase", and "tableView:cellForRow indexPath:" methods; replace with the code defined below:

FCViewController.swift

   
 deinit 
  
 { 
  
 if 
  
 let 
  
 refHandle 
  
 = 
  
 _refHandle 
  
 { 
  
 self 
 . 
 ref 
 . 
 child 
 ( 
 "messages" 
 ). 
 removeObserver 
 ( 
 withHandle 
 : 
  
 _refHandle 
 ) 
  
 } 
  
 } 
  
 func 
  
 configureDatabase 
 () 
  
 { 
  
 ref 
  
 = 
  
 Database 
 . 
 database 
 (). 
 reference 
 () 
  
 // Listen for new messages in the Firebase database 
  
 _refHandle 
  
 = 
  
 self 
 . 
 ref 
 . 
 child 
 ( 
 "messages" 
 ). 
 observe 
 (. 
 childAdded 
 , 
  
 with 
 : 
  
 { 
  
 [ 
 weak 
  
 self 
 ] 
  
 ( 
 snapshot 
 ) 
  
 - 
>  
 Void 
  
 in 
  
 guard 
  
 let 
  
 strongSelf 
  
 = 
  
 self 
  
 else 
  
 { 
  
 return 
  
 } 
  
 strongSelf 
 . 
 messages 
 . 
 append 
 ( 
 snapshot 
 ) 
  
 strongSelf 
 . 
 clientTable 
 . 
 insertRows 
 ( 
 at 
 : 
  
 [ 
 IndexPath 
 ( 
 row 
 : 
  
 strongSelf 
 . 
 messages 
 . 
 count 
 - 
 1 
 , 
  
 section 
 : 
  
 0 
 )], 
  
 with 
 : 
  
 . 
 automatic 
 ) 
  
 }) 
  
 } 
  
 func 
  
 tableView 
 ( 
 _ 
  
 tableView 
 : 
  
 UITableView 
 , 
  
 cellForRowAt 
  
 indexPath 
 : 
  
 IndexPath 
 ) 
  
 - 
>  
 UITableViewCell 
  
 { 
  
 // Dequeue cell 
  
 let 
  
 cell 
  
 = 
  
 self 
 . 
 clientTable 
 . 
 dequeueReusableCell 
 ( 
 withIdentifier 
 : 
  
 "tableViewCell" 
 , 
  
 for 
 : 
  
 indexPath 
 ) 
  
 // Unpack message from Firebase DataSnapshot 
  
 let 
  
 messageSnapshot 
  
 = 
  
 self 
 . 
 messages 
 [ 
 indexPath 
 . 
 row 
 ] 
  
 guard 
  
 let 
  
 message 
  
 = 
  
 messageSnapshot 
 . 
 value 
  
 as 
 ? 
  
 [ 
 String 
 : 
  
 String 
 ] 
  
 else 
  
 { 
  
 return 
  
 cell 
  
 } 
  
 let 
  
 name 
  
 = 
  
 message 
 [ 
 Constants 
 . 
 MessageFields 
 . 
 name 
 ] 
  
 ?? 
  
 "" 
  
 let 
  
 text 
  
 = 
  
 message 
 [ 
 Constants 
 . 
 MessageFields 
 . 
 text 
 ] 
  
 ?? 
  
 "" 
  
 cell 
 . 
 textLabel 
 ?. 
 text 
  
 = 
  
 name 
  
 + 
  
 ": " 
  
 + 
  
 text 
  
 cell 
 . 
 imageView 
 ?. 
 image 
  
 = 
  
 UIImage 
 ( 
 named 
 : 
  
 "ic_account_circle" 
 ) 
  
 if 
  
 let 
  
 photoURL 
  
 = 
  
 message 
 [ 
 Constants 
 . 
 MessageFields 
 . 
 photoURL 
 ], 
  
 let 
  
 URL 
  
 = 
  
 URL 
 ( 
 string 
 : 
  
 photoURL 
 ), 
  
 let 
  
 data 
  
 = 
  
 try 
 ? 
  
 Data 
 ( 
 contentsOf 
 : 
  
 URL 
 ) 
  
 { 
  
 cell 
 . 
 imageView 
 ?. 
 image 
  
 = 
  
 UIImage 
 ( 
 data 
 : 
  
 data 
 ) 
  
 } 
  
 return 
  
 cell 
  
 } 
 

Test Message Sync

  1. Click the98205811bbed9d74.png Runbutton.
  2. Click the Sign in to get startedbutton to go to the messages window.
  3. Add new messages directly in Firebase console by clicking on the green + symbol next to the "messages" entry and adding an object like the following:f9876ffc8b316b14.png
  4. Confirm that they show up in the Friendly-Chat UI.

7. Send Messages

Implement Send Message

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.

Modify your FCViewController's "sendMessage:" method; replace with the code defined below:

FCViewController.swift

   
 func 
  
 sendMessage 
 ( 
 withData 
  
 data 
 : 
  
 [ 
 String 
 : 
  
 String 
 ]) 
  
 { 
  
 var 
  
 mdata 
  
 = 
  
 data 
  
 mdata 
 [ 
 Constants 
 . 
 MessageFields 
 . 
 name 
 ] 
  
 = 
  
 Auth 
 . 
 auth 
 (). 
 currentUser 
 ?. 
 displayName 
  
 if 
  
 let 
  
 photoURL 
  
 = 
  
 Auth 
 . 
 auth 
 (). 
 currentUser 
 ?. 
 photoURL 
  
 { 
  
 mdata 
 [ 
 Constants 
 . 
 MessageFields 
 . 
 photoURL 
 ] 
  
 = 
  
 photoURL 
 . 
 absoluteString 
  
 } 
  
 // Push data to Firebase Database 
  
 self 
 . 
 ref 
 . 
 child 
 ( 
 "messages" 
 ). 
 childByAutoId 
 (). 
 setValue 
 ( 
 mdata 
 ) 
  
 } 
 

Test Sending Messages

  1. Click the98205811bbed9d74.png Runbutton.
  2. Click Sign Into go to the messages window.
  3. Type out a message and hit send. The new message should be visible in the app UI and in the Firebase console.

8. Store and Receive images

Confirm Firebase Storage Dependency

In the dependencies block of the Podfile , confirm Firebase/Storage is included.

Podfile

  pod 
  
 ' 
 Firebase 
 / 
 Storage 
 ' 
 

Set up Cloud Storage for Firebase

Here's how to set up Cloud Storage for Firebase in your Firebase project:

  1. In the left-panel of the Firebase console, expand Buildand then select Storage .
  2. Click Get started.
  3. Select a location for your default Storage bucket.
    Buckets in US-WEST1 , US-CENTRAL1 , and US-EAST1 can take advantage of the "Always Free" tier for Google Cloud Storage. Buckets in all other locations follow Google Cloud Storage pricing and usage .
  4. Click Start in test mode. Read the disclaimer about the security rules.
    Later in this codelab, you'll add security rules to secure your data. Do not distribute or expose an app publicly without adding Security Rules for your Storage bucket.
  5. Click Create.

Configure FirebaseStorage

FCViewController.swift

   
 func 
  
 configureStorage 
 () 
  
 { 
  
 storageRef 
  
 = 
  
 Storage 
 . 
 storage 
 (). 
 reference 
 () 
  
 } 
 

Receive images in existing messages

Add code that downloads images from Firebase Storage.

Modify your FCViewController's "tableView: cellForRowAt indexPath:" method; replace with the code defined below:

FCViewController.swift

   
 func 
  
 tableView 
 ( 
 _ 
  
 tableView 
 : 
  
 UITableView 
 , 
  
 cellForRowAt 
  
 indexPath 
 : 
  
 IndexPath 
 ) 
  
 - 
>  
 UITableViewCell 
  
 { 
  
 // Dequeue cell 
  
 let 
  
 cell 
  
 = 
  
 self 
 . 
 clientTable 
  
 . 
 dequeueReusableCell 
 ( 
 withIdentifier 
 : 
  
 "tableViewCell" 
 , 
  
 for 
 : 
  
 indexPath 
 ) 
  
 // Unpack message from Firebase DataSnapshot 
  
 let 
  
 messageSnapshot 
 : 
  
 DataSnapshot 
 ! 
  
 = 
  
 self 
 . 
 messages 
 [ 
 indexPath 
 . 
 row 
 ] 
  
 guard 
  
 let 
  
 message 
  
 = 
  
 messageSnapshot 
 . 
 value 
  
 as 
 ? 
  
 [ 
 String 
 : 
 String 
 ] 
  
 else 
  
 { 
  
 return 
  
 cell 
  
 } 
  
 let 
  
 name 
  
 = 
  
 message 
 [ 
 Constants 
 . 
 MessageFields 
 . 
 name 
 ] 
  
 ?? 
  
 "" 
  
 if 
  
 let 
  
 imageURL 
  
 = 
  
 message 
 [ 
 Constants 
 . 
 MessageFields 
 . 
 imageURL 
 ] 
  
 { 
  
 if 
  
 imageURL 
 . 
 hasPrefix 
 ( 
 "gs://" 
 ) 
  
 { 
  
 Storage 
 . 
 storage 
 (). 
 reference 
 ( 
 forURL 
 : 
  
 imageURL 
 ). 
 getData 
 ( 
 maxSize 
 : 
  
 INT64_MAX 
 ) 
  
 {( 
 data 
 , 
  
 error 
 ) 
  
 in 
  
 if 
  
 let 
  
 error 
  
 = 
  
 error 
  
 { 
  
 print 
 ( 
 "Error downloading: 
 \( 
 error 
 ) 
 " 
 ) 
  
 return 
  
 } 
  
 DispatchQueue 
 . 
 main 
 . 
 async 
  
 { 
  
 cell 
 . 
 imageView 
 ?. 
 image 
  
 = 
  
 UIImage 
 . 
 init 
 ( 
 data 
 : 
  
 data 
 !) 
  
 cell 
 . 
 setNeedsLayout 
 () 
  
 } 
  
 } 
  
 } 
  
 else 
  
 if 
  
 let 
  
 URL 
  
 = 
  
 URL 
 ( 
 string 
 : 
  
 imageURL 
 ), 
  
 let 
  
 data 
  
 = 
  
 try 
 ? 
  
 Data 
 ( 
 contentsOf 
 : 
  
 URL 
 ) 
  
 { 
  
 cell 
 . 
 imageView 
 ?. 
 image 
  
 = 
  
 UIImage 
 . 
 init 
 ( 
 data 
 : 
  
 data 
 ) 
  
 } 
  
 cell 
 . 
 textLabel 
 ?. 
 text 
  
 = 
  
 "sent by: 
 \( 
 name 
 ) 
 " 
  
 } 
  
 else 
  
 { 
  
 let 
  
 text 
  
 = 
  
 message 
 [ 
 Constants 
 . 
 MessageFields 
 . 
 text 
 ] 
  
 ?? 
  
 "" 
  
 cell 
 . 
 textLabel 
 ?. 
 text 
  
 = 
  
 name 
  
 + 
  
 ": " 
  
 + 
  
 text 
  
 cell 
 . 
 imageView 
 ?. 
 image 
  
 = 
  
 UIImage 
 ( 
 named 
 : 
  
 "ic_account_circle" 
 ) 
  
 if 
  
 let 
  
 photoURL 
  
 = 
  
 message 
 [ 
 Constants 
 . 
 MessageFields 
 . 
 photoURL 
 ], 
  
 let 
  
 URL 
  
 = 
  
 URL 
 ( 
 string 
 : 
  
 photoURL 
 ), 
  
 let 
  
 data 
  
 = 
  
 try 
 ? 
  
 Data 
 ( 
 contentsOf 
 : 
  
 URL 
 ) 
  
 { 
  
 cell 
 . 
 imageView 
 ?. 
 image 
  
 = 
  
 UIImage 
 ( 
 data 
 : 
  
 data 
 ) 
  
 } 
  
 } 
  
 return 
  
 cell 
  
 } 
 

9. Send Image Messages

Implement Store and Send Images

Upload an image from the user, then sync this image's storage URL to database so this image is sent inside the message.

Modify your FCViewController's "imagePickerController: didFinishPickingMediaWithInfo:" method; replace with the code defined below:

FCViewController.swift

   
 func 
  
 imagePickerController 
 ( 
 _ 
  
 picker 
 : 
  
 UIImagePickerController 
 , 
  
 didFinishPickingMediaWithInfo 
  
 info 
 : 
  
 [ 
 String 
  
 : 
  
 Any 
 ]) 
  
 { 
  
 picker 
 . 
 dismiss 
 ( 
 animated 
 : 
  
 true 
 , 
  
 completion 
 : 
 nil 
 ) 
  
 guard 
  
 let 
  
 uid 
  
 = 
  
 Auth 
 . 
 auth 
 (). 
 currentUser 
 ?. 
 uid 
  
 else 
  
 { 
  
 return 
  
 } 
  
 // if it's a photo from the library, not an image from the camera 
  
 if 
  
 #available 
 ( 
 iOS 
  
 8.0 
 , 
  
 * 
 ), 
  
 let 
  
 referenceURL 
  
 = 
  
 info 
 [ 
 UIImagePickerControllerReferenceURL 
 ] 
  
 as 
 ? 
  
 URL 
  
 { 
  
 let 
  
 assets 
  
 = 
  
 PHAsset 
 . 
 fetchAssets 
 ( 
 withALAssetURLs 
 : 
  
 [ 
 referenceURL 
 ], 
  
 options 
 : 
  
 nil 
 ) 
  
 let 
  
 asset 
  
 = 
  
 assets 
 . 
 firstObject 
  
 asset 
 ?. 
 requestContentEditingInput 
 ( 
 with 
 : 
  
 nil 
 , 
  
 completionHandler 
 : 
  
 { 
  
 [ 
 weak 
  
 self 
 ] 
  
 ( 
 contentEditingInput 
 , 
  
 info 
 ) 
  
 in 
  
 let 
  
 imageFile 
  
 = 
  
 contentEditingInput 
 ?. 
 fullSizeImageURL 
  
 let 
  
 filePath 
  
 = 
  
 " 
 \( 
 uid 
 ) 
 / 
 \( 
 Int 
 ( 
 Date 
 . 
 timeIntervalSinceReferenceDate 
  
 * 
  
 1000 
 )) 
 / 
 \(( 
 referenceURL 
  
 as 
  
 AnyObject 
 ) 
 . 
 lastPathComponent 
 ! 
 ) 
 " 
  
 guard 
  
 let 
  
 strongSelf 
  
 = 
  
 self 
  
 else 
  
 { 
  
 return 
  
 } 
  
 strongSelf 
 . 
 storageRef 
 . 
 child 
 ( 
 filePath 
 ) 
  
 . 
 putFile 
 ( 
 from 
 : 
  
 imageFile 
 !, 
  
 metadata 
 : 
  
 nil 
 ) 
  
 { 
  
 ( 
 metadata 
 , 
  
 error 
 ) 
  
 in 
  
 if 
  
 let 
  
 error 
  
 = 
  
 error 
  
 { 
  
 let 
  
 nsError 
  
 = 
  
 error 
  
 as 
  
 NSError 
  
 print 
 ( 
 "Error uploading: 
 \( 
 nsError 
 . 
 localizedDescription 
 ) 
 " 
 ) 
  
 return 
  
 } 
  
 strongSelf 
 . 
 sendMessage 
 ( 
 withData 
 : 
  
 [ 
 Constants 
 . 
 MessageFields 
 . 
 imageURL 
 : 
  
 strongSelf 
 . 
 storageRef 
 . 
 child 
 (( 
 metadata 
 ?. 
 path 
 ) 
 ! 
 ). 
 description 
 ]) 
  
 } 
  
 }) 
  
 } 
  
 else 
  
 { 
  
 guard 
  
 let 
  
 image 
  
 = 
  
 info 
 [ 
 UIImagePickerControllerOriginalImage 
 ] 
  
 as 
 ? 
  
 UIImage 
  
 else 
  
 { 
  
 return 
  
 } 
  
 let 
  
 imageData 
  
 = 
  
 UIImageJPEGRepresentation 
 ( 
 image 
 , 
  
 0.8 
 ) 
  
 let 
  
 imagePath 
  
 = 
  
 " 
 \( 
 uid 
 ) 
 / 
 \( 
 Int 
 ( 
 Date 
 . 
 timeIntervalSinceReferenceDate 
  
 * 
  
 1000 
 )) 
 .jpg" 
  
 let 
  
 metadata 
  
 = 
  
 StorageMetadata 
 () 
  
 metadata 
 . 
 contentType 
  
 = 
  
 "image/jpeg" 
  
 self 
 . 
 storageRef 
 . 
 child 
 ( 
 imagePath 
 ) 
  
 . 
 putData 
 ( 
 imageData 
 !, 
  
 metadata 
 : 
  
 metadata 
 ) 
  
 { 
  
 [ 
 weak 
  
 self 
 ] 
  
 ( 
 metadata 
 , 
  
 error 
 ) 
  
 in 
  
 if 
  
 let 
  
 error 
  
 = 
  
 error 
  
 { 
  
 print 
 ( 
 "Error uploading: 
 \( 
 error 
 ) 
 " 
 ) 
  
 return 
  
 } 
  
 guard 
  
 let 
  
 strongSelf 
  
 = 
  
 self 
  
 else 
  
 { 
  
 return 
  
 } 
  
 strongSelf 
 . 
 sendMessage 
 ( 
 withData 
 : 
  
 [ 
 Constants 
 . 
 MessageFields 
 . 
 imageURL 
 : 
  
 strongSelf 
 . 
 storageRef 
 . 
 child 
 (( 
 metadata 
 ?. 
 path 
 ) 
 ! 
 ). 
 description 
 ]) 
  
 } 
  
 } 
  
 } 
 

Test Sending and Receiving Image Messages

  1. Click the98205811bbed9d74.png Runbutton.
  2. Click Sign Into go to the messages window.
  3. Click "add a photo" icon to pick a photo. The new message with the photo should be visible in the app UI and in the Firebase console.

10. Congratulations!

You have used Firebase to easily build a real-time chat application.

What we've covered

  • Realtime Database
  • Federated Sign In
  • Storage

Learn More

Create a Mobile Website
View Site in Mobile | Classic
Share by: