Hey there, iOS 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 my app that I'm going to configure
using Firebase remote config.
I've got a button here on my view controller.
And you can see that, off in the code,
I have added both the button as an IBOutlet
as well as the constraint that positions it
near the top of the screen.
So in the course of this screencast,
we're going to do three things.
First, we're going to take our two values--
the text of the button and the constant of our constraint--
and give them to remote config as defaults.
Second, we'll ask remote config to download any 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.
So I've already gone ahead and created a project
in the Firebase console, setup CocoaPods,
configured my Xcode project, and initialized Firebase.
Don't know what I'm talking about?
Check out this Getting Started video first.
All right, so next step we need to make sure
that remote config is actually installed.
So go to your pod file here and add the Firebase/RemoteConfig
pod if it's not in there yet.
Run a pod install.
And then open up your XE workspace.
And all right, it looks like we're
ready to use remote config.
But before we do, maybe let's take a little moment
to understand 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.
Next, you're going to tell remote config to fetch
updated values from the cloud.
Very often, this will be just a subset of the default values
that you supply, right?
Like you only need to supply these new values from the cloud
when they're different from the defaults that you have 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.
Now, the reason these values don't get applied automatically
is that you could get into weird situations
when your absent values change, like right
while your user's in the middle of using your app.
And that could get all sorts of weird.
So when you tell remote config to activate
these recently-downloaded values,
they will then be applied on top of whatever
values you already have.
At that point, when you ask to retrieve
a value for a certain key, remote config
will either give you the default value or a newer value
that it's downloaded from the cloud.
Make sense?
All right, well, let's try that now in our app.
So before you do anything else, let's go ahead
and import the Firebase module.
Remember, this is all I need to do no matter what Firebase
CocoaPod I've got installed.
Now, I'll start by creating a set
up remote config method in which I'll supply my default values.
There's a couple of ways you can set up default
values in remote config.
You can either add them through a p-list.
Or you can use an NSDictionary.
I'm going to go with the dictionary approach here.
So let's create our NSDictionary with our button text
equal to-- let's call it-- default and our button
constraint constant key equal to, oh, let's say, 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 kind of bad form.
So our recommendation here is go ahead
and put all the values you might ever
want to change into this dictionary of default values,
right?
Like all your hard-coded strings, your magic numbers--
you know, what have you.
In essence, this should replace whatever
app constants file you've got lying around in your app.
Yes, we all have one of those.
I know.
So remember, you only download values
from the cloud that are different from your defaults.
So adding all these defaults won't increase
the size of your network calls.
But it will give you the flexibility
to change any of those values later if you want.
You don't want to be in a position
three months later when you decide, oh, you know,
I really should change the speed of my animations
and realize that that animation speed hasn't been wired up
to use remote config.
Next up, we can access remote config, which we'll always
do you through the remote config shared singleton instance.
And we'll call set defaults and then pass along
that dictionary.
All right.
So far, so good.
Now that we have 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 completion handler.
This method by default will only fetch new values
if the ones it already has are more than 43,200 seconds old,
which is 12 hours to you and me.
But that's also a long time to wait
if you're trying to test out remote config
changes in your app.
So instead, I'm going to call a fetch with expiration duration
completion handler and give our expiration duration
of value of, say, 0 seconds to make sure I'm always
fetching a new version.
Now, normally this would cause our app
to get throttled pretty badly by the remote config service.
But you can fix this by turning on developer mode, which
essentially removes this calls-per-user throttle
for a small number of users.
I'll create a settings object with developer mode enabled
set to Yes, or True if you're on Swift.
We can now 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 without getting throttled.
But don't do this in production.
Remote config will stop working.
In fact, I kind of like sticking everything behind a debug flag,
sort of like this.
We'll pull out our expiration time into a separate variable.
You can set it to 0 if we're in debug mode and 43,200
if we're not.
And yeah, that's probably a little safer.
Anyway, we can now go ahead and fetch these new values.
And I'm going to do two things in our completion handler.
First off, I'll print out a happy little message
to our console.
And then we'll also call activate fetch.
Remember, this tells remote config
that it's OK to take those values that we fetched
from the cloud and apply them on top of our current values.
So we'll run this.
And we can see that we've successfully made a call
to the internet-- hooray!
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.
Let's tackle that next.
So I'm going to create a method called update view, 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 up here, right after I set up my default values
and then again to here on my fetch call back so
that I can apply any new values that might have come in.
Now, calling self from within a block like this
could lead to a retain cycle.
So just to be safe, I'm going to add a weak self reference
in here a little like this.
There we go.
That's better.
Now, 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,
sort of like this, which is a little nicer sometimes.
Now, these values have a type of remote config value.
You can think of it kind of like an NSObject.
But you're almost never going to use them directly.
Instead, you're going to call one of its follow-up methods--
string value, number value, data value,
and so on-- to convert it to a usable data type.
It is 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 going back to my app here, I'm
now going to set my buttons title to remote config,
config value for key, button text--
because that's the key-- and then string value.
And then I'm going to set my constraints
constant to remote config, config value for key, button
constraint constant, number value-- which is an NSNumber--
and then float value to get the value as a CGFloat.
Now I can run this.
And you can see that my button's text and position are being set
by the remote config object.
It's pulling all the devalues from the defaults right now.
But let's see what happens if I set these new values
in the Firebase console.
So 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.
So the key parameter here is really just the name of the key
that I want to change.
And I'll start by adding button text here.
And we'll change its value to, Hello from the cloud.
I don't need to add quotes here or anything.
Everything's basically saved as a string at this point.
And that's it.
We'll run it.
And check it out, we got some new values.
You may have noticed there was this tiny moment when
my text flickered from the default value
to the newest values after it loaded them
from the remote config service.
And remember, that's because I called
applied fetched immediately instead of waiting for a more
opportune moment.
I won't see this again if I run my app again
because any values that are applied stay applied.
So you're not going to start off with pure defaults
every time you open up or start up your app.
Oh, but you know, for fun, let's change
the value of this constraint constant, too.
We'll change it to something like this and run it again.
And woo!
Look at that button scoot down.
So that's 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 that you don't get that little flicker when
your app gets new values, all of which
are very good topics for future videos.
In the meantime, please check out the remote config
documentation and go configure your apps from the cloud!
[MUSIC PLAYING]