(techno upbeat music)
- Hello everyone, and welcome. My name is Ryan.
I’m a Software Engineer on the Firebase team
working on Apple SDKs in our Waterloo, Canada office.
- And I'm Chen.
I am a Software Engineer on the Firebase team,
also working on Apple SDKs. I'm based in Sunnyvale, California office.
- Firebase's mission is to help developers succeed
by making it easy to build and operate apps.
- We know Firebase is a cross-platform, mobile developer toolkit,
supporting iOS along with Android, Web, CIMA+, and Unity.
But hey, we know why you're here.
If you're excited like me, you may find Apple’s ecosystem
has made it easier to develop multi-platform apps.
not just for iOS and iPadOS, but macOS, WatchOS, tvOS and Catalyst.
Whoa, that's a long list.
At Firebase, we’re looking into some use cases here
and making them available across Apple's platforms.
The Firebase SDKs for Apple platforms give you the flexibility to unlock
some iOS development flow,
and they will continue to do more in the future.
- Billing and running apps for iOS and other Apple platforms
has changed over the past few years.
Swift has become the de facto language for building apps.
We’ll cover some neat Swift language features and frameworks in this session.
SwiftUI, for example allows us to build beautiful interfaces
using a simple and concise syntax.
Swift Package Manager is easier than ever to include Firebase SDKs in your project.
Async/wait and Combine
are new ways we can reason about Asynchronous programming.
At Firebase, we're watching these changes closely
and today, we’ll show our approach to these changes in the ecosystem.
But first, Chen, what’s going on in the GitHub repo?
- Let me tell you, Ryan,
since Firebase took the first step of open sourcing our client libraries in 2017
the vast majority of Firebase SDK for Apple platforms
are available today on GitHub.
We recently opened source the Firebase performance SDK
at the end of 2020. So in case you haven't seen it yet
go check it out and let us know what you think.
We continue to show our commitment of greater transparency
and building a stronger developer community.
To this day, we’ve closed over 2,000 issues and emerged over 5,000 pull requests.
Our Firebase team loves the interaction with you on GitHub.
We encourage you to voice your feedback,
no matter the feature requests or bugging issues,
because you can talk directly to our engineers
who build on the SDKs, including Ryan and me.
It also makes the technical conversations much easier.
We’re fortunate to have an amazing community of contributors.
There are currently 139 of you
contributing on Firebase SDK for Apple platforms.
We’re seeing active open source collaborations
between the community members and Firebasers
working together on combined support.
We want to give a big thank you to all of you for making our SDKs better.
Being an open source has made many things possible.
Being able to step through code
save hours of bug huntings.
It also enabled features like community support
for tvOS, macOS, Catalyst and WatchOS.
We recently added community WatchOS support
for real-time database and remote config.
Now you can try this out in your watch app
and use GitHub discussions to ask any questions.
Many of you have already started using Swift Package Manager
to manage dependencies.
Today, Firebase is officially supporting Swift Package Manager.
So in addition to (inaudible), now use Swift Package Manager
to add Firebase libraries to your app.
Here, I’ll quickly show you how to do it because it’s really easy.
First, you will need to get the URLs from the Firebase iOS SDK report page.
Copy-paste the URLs from the page.
This should work for most libraries that are hosted on or distributed via GitHub.
Now, open your app in your X code, click on the File tab,
and select the Swift Package. Then click on Add Package Dependency,
paste the URLs, and click Next.
Select the version or branch you want to target.
We recommend getting the latest version of our SDKs
not just for new features
but more importantly for bug fixes or improvements.
Shortly after, you’re able to select the product you want to use.
Here we’ll use Analytics Auth,
and we wanted to try out the new SwiftUI extension APIs.
One thing to know is, if you want to add it in a different target,
say you have an independent watch target,
and you only want to install messaging inside the watch app,
you can choose a target on the right side.
When you’re done, click and finish, then you should be able to see the packages
if you click Project and selects Swift Packages here.
If you wants to add more Firebase SDKs later,
you can go to the target you want to edit, click on General,
and under the Frameworks, Libraries and Embedded Content.
You can manually add Firebase SDKs, or delete some if you no longer need it.
Now that we created a new project with Swift Package Manager,
let’s hear from Ryan to talk more about Swift and SwiftUI.
- Thanks Chen.
Despite our SDKs being written mostly in Objective C,
we evaluate every single API to see how it gets imported into Swift
and try to make the experience great.
But, what about things like result types, codeable support,
default parameters, or enums and associated types?
We can take advantage of those great Swift features
when writing Objective C. Sometimes we just need to write Swift code.
That’s why we started shipping optional Swift extensions to different SDKs.
And some have been contributed by the community.
Let's go over some highlights. We're gonna be looking at a lot of code.
Here’s a snippet where we’re downloading a picture from Firebase storage
using the traditional completion handler block.
Both data and error are optional
and that leads to some awkward code causing us to force and wrap the error.
Not something we want to do if we avoid it.
The error should always be populated when data is nil,
and data should always be nil when there’s an error.
But we can’t enforce that in the compiler using the existing code.
By switching to use the function the new Swift extension provided,
we can eliminate that awkward state and the force unwrap.
Using a switch statement, we get the compiler safety
of only having two states represented. We have data or we have an error.
No more in between states. Let’s move on to Firestore and parsing data.
This is a shortened code snippet showing data-parsing from a previous version
of our Firestore quick start out. After getting the data from firestore
we want to convert it into a local type from the dictionary provided,
in this case, a restaurant. Does this kind of code look familiar to you?
It makes me sad every time I read the menu. Unwrapping an error on string keys,
not taking advantage of Swift's type safety features.
It’s fragile, hard to read, and easy to make mistakes when writing it.
Instead, let's add codeable conformance to our restaurant type.
By confirming to the codeable protocol,
we get a lot of that manual code parsing for free
as it’s generated by the compiler, and updates stay consistent across the type.
Reading that Firestore data
is now as easy as calling the data as function
on documents, snapshot and parsing in the restaurant type.
No more manually parsing that object. Codeable does all the work for us.
Setting the data in firestore is just as easy,
passing in the instance directly instead of a dictionary representation of it.
We also just published a similar API for Firebase database,
thanks to an external contributor.
Next, the new and exciting SwiftUI. This one's my favorite.
I’m excited to share we recently shipped some SwiftUI-specific APIs with more to come.
At WWDC 2020, we were introduced to a new SwiftUI app life cycle
that's shared across platforms.
Previously, we recommended you put FirebaseApp.configure
at the top of your app that finished launching call in your app delegate.
Well, where does it go if there's no app delegate?
We simply override the init function that gets called when an app starts
and call FirebaseApp.configure there.
This remains true even if you need to use a UI application delegated after
to handle things like push notifications,
which we'll see later on in a demo from Chen.
The first new API I wanted to show you is for logging manual screen view events
in Google Analytics for Firebase. Their existing API
is to automatically record screen views and screen classes for UI kit,
but due to the fact SwiftUI
does not have a corresponding UI view controller that we can tap into,
that doesn't work when using SwiftUI.
Thankfully, last year we added a manual screen view event
so you could have careful control over when these events were logged.
That fits in when writing UI kit. Integrating this into your viewDid/Appear,
it stays mostly out of the way.
Let’s look at what this looks like in SwiftUI.
We can call these manual logging APIs
whenever a view appears using the on appear modifier.
So this works, but it’s pretty verbose and can clutter code
and take away from the structure of your view.
Rather limit with what we can offer from an API standpoint in objective C,
but we can do better in Swift.
This looks like a great opportunity for custom view modifier,
and that's exactly what we built.
We can now mark up any view
with the provided analytics screen view modifier
to declare the name of the view, the class or in this case, the struct,,
but we’re matching the existing analytics naming here
and any extra parameters you'd like to be logged
when this view appears on screen.
And thanks to Swift’s default arguments, you can provide just the name
and the rest is optional. Like in this case,
we're leaving out the extra parameters argument.
We’re so excited about this new way
to mark up your views and record screen view events.
Another SwiftUI improvement we shipped is to build your own in-app message views.
In this example, we’re using the modalInAppMessage modifier.
The closure is a view builder
and the arguments are the message which contains the data
that was configured in the console,
plus the delegate to notify the in-app messaging SDK
of interactions, like when a message is tapped or dismissed
in order to record metrics and impressions.
There’s APIs covering each message type that make providing custom interfaces
from your in-app messages, easier than ever.
Let us know in GitHub discussion if you have any ideas
for other SwiftUI helpers you’d like to see.
The community is excited about Combined and we can't blame them.
We are too. We've received some amazing contributions
from folks in the community
and have been working on some changes ourselves.
There’s still work to do in this space
but here’s a sneak peek at what you can expect.
This is a publisher we wrote for Auth's sign-in using an email and password.
It returns a combined future
of the Auth data result or the associated error.
This is a bit simplified, but in this pipeline,
we are extracting the user, replacing any errors with nil,
and assigning it to our signed-in user property
that gets represented in the UI.
We've got multiple publishers across different STKs
to help you with your Async data flow.
You can keep an eye on progress in our combined APIs
using the GitHub project we have set up. Combine isn't the only exciting progress
made on Async handling code. We're very close to seeing Async/await
in a released version of the Swift tool chain.
Let’s take another look at sign in with email and password,
comparing the completion handler to Async/await.
Here, we use completion handlers to handle the control flow.
Inside of that completion handler, we may want to do more asynchronous calls
which can lead to the classic pyramid of doom.
How does Async/await transform this call?
Instead of managing the state entirely in the completion handler block,
it looks more like synchronous code and is easier to reason about.
We can continue to do the same for other Async calls
and it's gonna be far simpler to maintain state
and make sure errors are handled appropriately.
Now I'd like to pass it back to Chen for an exciting demo.
- Thanks, Ryan.
Now let’s discuss how you can do the independent watch app with Firebase.
Say you’d like to track your daily coffee intakes on your watch.
A cool thing about independent watch app is that the users can use it without a need
to sync from their phones.
Firebase is working on making your watch app development easier
by connecting watch directly to Firebase Cloud service.
Currently, we’ve several products that have community support for WatchOS
so that you can, for example, send push notifications
from the Firebase console directly to your watch app.
Sync your coffee intake progress with our real-time database
without a companion phone.
Or download the image from cloud storage directly to your watch.
One thing to know is that the apps you set up on the console
should be one-on-one matching of the apps in Apple Store Connect.
If the app covers multiple platforms, use a single fibrous app
and the Google service info plist for all the platforms that app runs on.
This applies to iOS app extensions as well.
For example, if an app has an iOS app, a Mac app and the widget target,
you can simply import the main app’s Google servers info plist file to all targets.
Now that you’ve set up your Firebase product successfully
and then import the plist files to X code, let’s come back to how we can send
push notifications directly to your watch app.
We're using the latest SwiftUI lifecycle here.
So you will notice there's no extension delegate available.
This is because a SwiftUI life cycle, by default,
does not include any app or extension type delegate.
What you can do here is to use WKExtension delegate adapter
to inject the delegate to your app where you can add code
to request WatchOS push notification permissions
and handle any Firebase SDKs API that require an app delegate to exist.
For this case, you need to set an apnsToken to messaging SDK.
In the past, this step was handled automatically by messaging
when swizzling was enabled.
However, as swizzling has become more fragile,
we no longer recommend this approach on WatchOS.
Instead, you need to implement a deed registered
for remote notifications method from the WKExtension delegate
to manually set apnsToken to messaging.
The same applies to the iOS app if you use a SwiftUI lifecycle.
You need to use the UI application delegated adapter
to inject your own app delegate from the UI kit.
Then you can implement code that requires app delegate to exist.
Now let me show you a snippet of code on how to download a cute sparkly image
directly to your watch app. We’re using the Firebase storage here.
Oh, did you notice the exact same code can run on your iOS app as well?
Yes, because Firebase storage
does not require a special watch key API like messaging.
You can have almost identical code for your WatchOS, iOS, tvOS, macOS apps.
We also unlocked some app extension support
because they're really helpful making it easier
for users to access your app and do more fun things.
Take widget as an example.
Widget extension is a great way of presenting your app information
and making it more appealing for users to click on.
Here's a code snippet where you can pull pictures
using storage to your widget extension.
And with that, you get a sparkly one on your widget kit also.
And it's a great way to show some key info of your app to the users
instead of basic icon, which is pretty cool.
And that's it.
We hope you had a great time building Apple apps with us.
Definitely check out our GitHub repo.
There’s a lot of useful info you can find there.
Try it out, follow bugs, and start GitHub discussions.
We can’t wait to see what you can build with Firebase.
(techno upbeat music)