TODD KERPELMAN: Hey there, Swift developers.
Interested in getting started with Remote Config on iOS?
Well, you've come to the right place.
Let's update our app from the cloud
on this episode of "Firecasts."
[MUSIC PLAYING]
So here's an app I'm going to configure using Firebase Remote
Config.
I've got a button here in my view controller.
And off in the code, you can see that I've gone ahead
and added both the button as an IB Outlet
as well as the constraint that positions it
near the top of the screen.
Now, in the course of this video,
we're going to do three things.
First, we're going to take our two
values, the text of this button and the constant
of our constraint, and supply them
to Remote Config as defaults.
Second, we'll ask Remote Config to download new values
from the cloud, if they exist.
And third, we'll wire up our app to use these new values so
that we can change the look of our button
from the Firebase console without having
to touch our app.
So go ahead and get your own app to follow along with.
As long as you have a few values of your own to play with,
you should be just fine.
Now, I've already gone ahead and created a project
in the Firebase console, added my Google services plist file
to my Xcode project, installed Firebase through CocoaPods,
and initialized Firebase.
If you don't know what I'm talking about,
you should check out this video first.
As for the rest of you, let's get hacking.
So first up, we need to make sure Remote Config is actually
installed.
So go to your Podfile and add in the line pod firebase
slash remote config, if it's not there yet.
We'll save and run a pod install--
doo, doo, dah, doo--
and then open up your XE workspace.
OK, we're ready to use Remote Config.
But before we do, let's take a moment
to understand a little about how Remote Config generally works.
So with Remote Config, you first start off
by giving it a bunch of default values stored as key value
pairs.
And these are just defined locally by your app,
either in a dictionary or a plist file.
Next, you tell Remote Config to fetch updated values
from the cloud.
Very often, this will be a subset of the default
values here, right?
You only need to supply ones where
the values that you are downloading
are different from the defaults you supplied locally.
Remote Config will then keep these values
in kind of a cached holding pattern on the device
until you tell it to apply them.
And the reason these values don't get applied automatically
is that you could get into weird situations
when your app's values change when you're not expecting them
to.
So when you tell Remote Config to activate these recently
download values, they will then be
applied on top of whatever values you already have.
Then when you ask to retrieve a value for a certain key,
Remote Config will either give you
the default value or some newer value
that you've downloaded from the cloud and applied on top.
And so our recommendation here is go ahead and put
all the values you might ever want
to change into this dictionary-- all your hard-coded strings,
magic numbers, anything you've got in that appconstants.swift
file that we all have in our app somewhere.
Remember, because you're only downloading values
from the cloud that are different from your defaults,
this won't really increase the size of your network calls.
But it will give you the flexibility
to change any of these values later if you want.
You don't want to be in a position three months
down the road when you decide, oh, I really
should change the speed of my animations,
and then you realize you haven't wired up those values to use
Remote Config.
Make sense?
All right, well, let's try that now with our app.
So I'm going to jump into my ViewController here.
And before I do anything else, let's
go ahead and import Firebase.
Now, remember, this is the only importing
I need to do no matter what Firebase CocoaPods
I've got installed.
Next, I'll create a setupRemoteConfig defaults
method in which I'll supply my default values.
Now, there are a couple of ways you can set up default
values in your Remote Config.
You can add them through a plist,
or you can use a dictionary of strings and NSObjects.
And I'm going to go with the dictionary approach here.
So let's create our default values
with our buttonText equal to Default text
and our buttonConstraintConstant key equal to 50.
And yes, if this were a real app,
I wouldn't want to be typing out the names
of these keys like that.
That's bad form.
I would use an enum instead.
Next up, we can access Remote Config, which we always
do through the remoteConfig shared singleton instance.
And then we'll call setDefaults and pass along our dictionary.
OK, so far, so good.
Now that we have these defaults, we'll
fetch in any new values from the cloud.
So let's create a second fetch remote config
method to do that.
So one method you could call at this point
is fetch with completionHandler.
That method, by default, will only fetch new values
if the ones it already has are more than 43,200 seconds old.
That's 12 hours to you and me.
But that's kind of a long time to wait
if you're trying to test out Remote Config
changes in your app.
So instead, we can call fetchWithExpirationDuration
expiration completionHandler and give our expiration duration
a value of, say, 0 seconds to make sure we always
fetch a new version.
Normally, this would cause our app
to get throttled pretty badly by the Remote Config library.
But you can fix this by turning on Developer mode, which
will increase this calls per user throttle
locally on the device.
So I'll create a settings object with Developer Mode enabled
set to true.
We'll set our config settings to be this new object.
And we're good to go.
This will let your app fetch Remote Config values a lot more
frequently before it gets throttled.
But don't do this in production, or you'll
start hitting the server-side throttle,
and Remote Config will stop working.
In fact, let's put in a big old FIXME
to remind myself later to take this out.
Anyway, we can now go ahead and fetch these values.
So let's tackle our completionHandler.
And I'm going to use the trailing closure method here,
which is what all the cool kids do these days.
So first, I'll confirm that we don't have any errors.
And then next, we'll print out a happy little message
to our console.
And then we will call activateFetched.
Remember, this call is what tell us Remote Config
that it's OK to take these values that we fetched
from the cloud and apply them on top of our current values.
And then let's make sure we call this after we set our defaults.
And now we can run it.
And all right!
We can see that we've successfully
made a call to the internet.
Awesome.
Of course, we're not actually doing anything
with any of these values in Remote Config.
So our app looks exactly the same
as before, which is kind of boring.
So let's tackle that step next.
I'm going to create a method called updateViewWithRCValues,
which will basically set my button text
and constraints based on the values I get back
from Remote Config.
And I'm going to call it in two places--
first down here, right after I set up my default values,
and then again here in my fetch callbacks that I
can apply any new values that might have come in.
Now, remember, calling self from within a block like this
could lead to a retain cycle.
So just to be safe, let's add in a weak reference
to self like this.
Time to fill out this method--
so grabbing values from Remote Config
is pretty straightforward.
You're going to call the config value for key method, which
retrieves the corresponding value from Remote Config.
You can also access these values directly with bracket notation,
like so.
Now, these values have a type of Remote Config value.
It's basically a wrapper around your value, which
is like a UTF-encoded string.
But you'll almost never use this type directly.
Instead, you're going to call one of its followup methods--
string value, number value, data value, bool value, et cetera--
to convert it to a usable data type.
Now, it's up to you to know what type of value you're expecting
and call the appropriate method so that Remote Config
can parse it correctly.
So let's do that.
So going back to my app here, I'm
now going to grab remoteConfig, configValueforKey
buttonText stringValue.
And this comes back with an optional string.
Remember, the Remote Config library
has no idea if the key that I'm providing actually exists.
So I'm going to use the double question mark operator here
to give it a default value of empty string
if, for some weird reason, this comes back as nil.
And now I can set that as our button's title for control
state normal.
And then let's get our button's constraint constant.
I'm going to use the brackets notation here
so you can see it in action--
very exciting.
We'll get its number value, which is an NSNumber, and then
FloatValue.
We'll set that as our constraint constant.
And now let's run it again.
All right, now you can see that my button's text and position
are being set by the Remote Config object.
It's pulling all of its values from the defaults right now.
So all we're seeing are these defaults.
But let's see what happens if I set these values
in the Firebase console.
I'm going to head over to the Firebase
console for my project.
And I'm going to select the Remote Config tab.
You can see that I'm being asked to create my first parameter.
So let's do that.
The key parameter here is really just the name
of the key I want to change.
And so I'll start by adding buttonText here.
And we'll change its value to "Hello from the cloud."
And that's it.
I'll publish my changes.
Now I'll go back into my app and run it again.
And check it out.
We got some new values.
And for fun, let's change the value of this constraint
constant, too.
We'll go back to the Firebase console,
add an entry for my button constraint constant.
We'll publish it and then go back.
And we'll just restart my app.
I'm going to kill it and run it directly from the simulator.
I don't even need to run it from Xcode.
And woo!
Look at that button scoot down.
So exciting!
So you may have noticed there was this tiny moment when
my text flickered from the default value
to the latest values after it loaded them
from the Remote Config service.
And that's because I called applyFetched and then update
my view immediately after fetching them instead
of waiting for a more opportune moment.
Now, obviously, this can lead to some awkward user experiences.
So there are better ways to load and apply
your values from Remote Config.
And as it turns out, I have a whole other video all about it.
You should check it out.
But that there is the basics of Remote Config for you.
There are certainly some other topics
to cover, including delivering different values
to different users, running an A/B test,
and applying fetch data intelligently
so you don't get that little flicker when your app gets
new values, all of which are very
good topics for other videos.
In the meantime, please check out the Remote Config
documentation and go configure your apps from the cloud.
Ooh, exciting.
[MUSIC PLAYING]
Thank you very much for watching.
Want some more exciting Firebase content?
Well, check out these videos here.
[MUSIC PLAYING]