Resources

Related Videos

WWDC 2017

I'm the manager of ICloud Web Services
and I couldn't be happier to be here today to tell you
about the number one feature request we received last year
for CloudKit, which is web services.
So this talk expects a little bit of familiarity
with CloudKit I will be giving you a brief overview
of the architecture but if you want a more deep dive we had a
couple of sessions last year.

You can go back and review those sessions.
So in CloudKit, all of your data is stored within a container.
Inside of this container we have a public database
for your app data and a private database
where your user date is stored.
In the public database, you have the default zone,
which has records, and in the private database,
you also have a default zone,
but you can also create custom zones which add sync semantics
which allow you to answer the question what has changed
since a given point in time.
Of course, you can create records in both of these zones.

From the API perspective, we have the CloudKit Server,
and on the native side we have the CloudKit Framework,
which your app uses to interface with the server.

We are introducing CloudKit Web Services today,
which we have used to build the Notes Web app,
and today you can use to build your web app.

So what exactly is the CloudKit Web Service?
Well, it's three things.
Number one, it's a JSON interface to CloudKit.

Number two, it's a web sign-in with Apple ID and number three,
it's a JavaScript library.
So let's take a look at the JSON API features.

So your full public and private database access, you can,
of course, create, read, update, and delete records.
You can upload and download assets.

You can query your data.
You can create subscriptions and receive call backs
when your data changes, you have user discoverability
where you can find users' real names.
You can do sync and we provide authentication.
So this is a long list, and in fact it means
that we have feature parity between the native API
and the JavaScript API.
So everything you can do in the native API you can do
through the JSON API and we have gone so far to make sure things
like field names and parameters have the same names
in JavaScript.
And JavaScript promises to provide completions.
Your code ends up looking similar
between JavaScript and Swift.
I know many of you
in the audience may already have a CloudKit application,
but if you don't, let's look quickly about how to get started
with a new CloudKit application.
So the first thing to do is to create a container.

You can do this either through the WWDR portal
or through Xcode.
Once you have the container you need to create a schema.

You can do this either through the iCloud dashboard
or your native Apple create it on demand.
So now you have your CloudKit application up and running.

Let's enable web access.
This is a three-step process.
Number one, you need to generate a web service API token.

Number two, you need to set your login call back mechanism,
and number three, you need to define your domain restrictions.
So let's take a closer look at these three steps.

So here is the CloudKit dashboard.
As you can see, we have added a new pane called API tokens
and I have already created my first token here.

So at the top is the token ID, which is what you pass
in when you make a web service call,
below that I have chosen post message as my login call back.

It is for JavaScript applications I will get a
JavaScript call back when the user logs in.
Alternatively I could have chosen to have a URL redirect.

Below that I can set the origins that are allowed
to access my CloudKit data through web services.
I have here chosen that any domain can access my data
but for added security I could have restricted
to viewer domains so now we have enabled web services.
Let's get some users to log in.

So authentication is handled transparently.
What I mean by that is when a user calls an API
that requires authentication,
we will return a specially formed payload
with a redirect URL that you can send your users to.
They then authenticate with an existing Apple ID
or they can create a new Apple ID right in the sign-in flow.
And to protect users' privacy we don't provide user name
or password to your app.

Instead we give you a stable anonymous identifier
for the user.
So let's put all of these things together
and let's build a quick example app.
So we are going to build a tasks app.
It stores tasks, and the com dot example dot tasks container.

So let's create our first task.
So what I will do is I will call the records modify API,
and pass in a JSON body.

This JSON body says to create a new task it has a unique
identifier task one and the value of the task is buy milk.
Let's go ahead and send that over to the server.

So we didn't have an authenticated user.
So in the response we get a redirect URL
where we can send the user to authenticate.

Let's go ahead and follow that URL.
So here is the sign-in UI.
You will notice it has the app name and the app icon
and the ability to create a new Apple ID right here.
We already have one, so let's go ahead and sign in.
Now, once the user is signed in, you will get a session ID back
to your application through the call back mechanism you
defined earlier.
So we can go ahead and append this session ID to the URL
and send the same request again.
Much better.
Now we receive back a successful creation.

You can see that the record name is there,
the change tag is there, the fields are there
and some more metadata about the record.

This is a lot of JSON parsing and you have to worry
about error handling and throttling and we want
to make this API as easy to use as possible.

So we are proud to introduce CloudKit JS a wrapper
on top of the JSON.
To talk about this I would
like to invite Onar Vikingstad to the stage.
I'm.
ONAR VIKINGSTAD: Engineering Manager at iCloud.

And I'm here to talk about CloudKit JS.
CloudKit JS lets you connect to CloudKit from JavaScript
and it's a small self-contained library that works well
with any framework or library you might already be using
on the web.
It's also important to note
that this is a low level transport API which means
that it doesn't really intend to be a data store.
It doesn't allow a lot of abstraction on top
of the JSON API so if you are already using a data store
please keep using that and you should be able
to plug CloudKit JS straight into it.

Also it allows for an easy transition
from CloudKit Framework.
So you might already be using CloudKit Framework on iOS
and OS X in the terms and concepts, method names
and class names are going to be the same
so it will be an easy transition.

That said, there will be some differences.
This is the web, after all, and it's JavaScript
so there will be a few differences,
for instance we are using JavaScript promises for all
of the asynchronous behavior
and we will see examples of that later on.

In terms of browser support, we support all
of the major browsers you would expect Safari, FireFox, Chrome,
Internet Explorer and the new Microsoft Edge.

We support Node JS if you want to do server
to server connections on behalf of the user.
So before we start looking more
at the API let me give you a quick demo.
So what we are looking at here is the CloudKit catalog sample
code project.

This is available both as a downloadable zip file,
you can get this on the developer website,
but what we are looking at here is the hosted version
which is also available.
So it is providing live code examples
that you can execute in any browser.

You will see a list of features on the left.
We are looking at the ReadMe right now.
This is giving you some instructions on how
to get started on CloudKit JS.
Let's move to the first section called authentication.
So you will notice each of these sections have a description
on top and this example is telling you how
to use authentication, and below that you have a code example.
So this code snippet specifically is checking
for authentication state of the user.
If the user is not already signed in,
it's going to present a signed in button.

And you can actually go ahead on top here and run this code.
So if I click this run code button,
it's going to execute this code, and you will see it scrolls
down through a section
and it tells us we aren unauthenticated user
at this point and we look at the sign-in button.

I can go ahead and click the sign-in button.
I type in any Apple ID and password.
And you notice the window closed.

And that was the Apple hosted authentication page.
So at this point your web application is signed in.
This is the sample app and you see we have the name
of the user, first and last name as well
as the sign-out button instead of the sign-in button.
This is another feature of CloudKit
which is discoverability.
If the user has opted in, the user can choose to share first
and last name with a developer as well as being discoverable
in the container for other users to find them.
So now that we have the first and last name we are using
that here to populate the top right corner.

All right.
So now that we are signed in, we can do some operations
so let's go to records.

And this is showing you how we can save a record
in the private database.
So we see a few fields on the top here.

We have the record name,
which is the unique identifier of the record.
We have a zone name which is the default zone
but it will be any custom zone that you set up,
and if you have three custom field names that are defined
in the CloudKit schema.

So in this example, we have a name field
which is the string value.
We have a location field, which is the geo location value
and then we have an asset field which lets you upload a file.
So I will go ahead and choose a file.
I will choose this green field landscape J Peg.

And I'm going to go back up on top
and give this the name landscape 1.
This is the record name which is the unique identifier.

And I will change the name here to just called it green field.
So now that I have the field filled out I can run the code
and it will save the record to the database as well
as upload assets to asset storage.
So you see when it's completed we are left with a result
and this is actually what the server responded with,
effectively with the JSON we are representing it here
in the table.
We have a few metadata fields as well
as the three custom feel fields.
The green field, the location and the link
to download the asset.

So just to show you this actually got stored we can go
to fetch record and I can type in landscape 1, run this code,
and we have the same record again.

That's how simple it is to save records
with CloudKit, with CloudKit JS.
Now, let's go and do another feature called querying.

So to do that, I will first go ahead and sign the user out.
So queries allow you to get subset of data
from the database, and in this code example,
we are showing you how we can query the public database
and if you set up the security roles appropriately
on the schema, you can actually query for data
in the public database even if the user is not authenticated
that we are showing here.
I can go ahead and run this code
and this example is basically using the current location
in a Monscone center to send a query and sort results based
on proximity to where we are currently.

I can go ahead and run the code.
And I get back two records.
The first one being Iceland, and the second one being Italy.

And Iceland is closer to where we are
than Italy, so that makes sense.
And so I'm not going to go through all
of the additional features
but we encourage you to check it out.
You can go to developer@Apple.com/CloudKit
and you can run this on any browser yourself.
So CloudKit is the foundation for a lot of our new services
at Apple including iCloud drive and iCloud photo library.
This year we also introduced a notes application
for iOS and OS X.

This is also coming to the CloudKit platform,
but in addition to the notes application
on native we have a notes web application on Apple.com.

In fact, it's using CloudKit JS in exactly the same way as you
as a developer can now use it.
There is no additional Apple magic here.

So hopefully you are as excited about CloudKit JS as we are
and see a lot of new possibilities here and want
to know how to get started.

So let's take a look.
So first off, we need to make sure you insert a script tag
on your web page, and you do this by pointing
to the CD unhosted version of CloudKit JS.
So this will get CloudKit JS included, and then secondly,
you need to configure the CloudKit instance.

So you are going to have the CloudKit name space available
and you can call the CloudKit configure method
and you give it a container identifier
that your application is using.
The environment you want to target, either production
or development, and then you specify the API token
that you saw Chris generate through the CloudKit dashboard.
That's all you need.
At this point you are ready to start making CloudKit API calls.

Next, you probably want to authenticate your users just
like we saw in the sample app.
So on iOS and OS X this is straight forward with CloudKit.

All you need to do since most users are already signed
into iCloud on the device is to call the fetch user method
on the container and you get back a user record
and this user record is going to have a stable identifier.
So this is all you really need to do to authenticate users
through CloudKit on the native devices.

There is no explicit login, there is no UI.
It's all seamless.
On the web, however, it's going to work a little bit differently
in that the browser is not already going to be signed
in so you have to provide a location for the sign-in button.
Like we saw on the sample app,
clicking it will open the new window.
There is an Apple hosted authentication page
and you notice on this page we have both the iCon
of the application as well as the name of the application,
and this is coming out of ITunes Connect
and it's published in the App Store.

And the user types in their user name and credentials.
This obviously only goes back to Apple.
There is also a two-step verification
if the account is set up for that.
And when this process completes, the window is going to close
and it's going to send back a post message
to the opener window and it will contain the CloudKit session.
So at this point your CloudKit JS,
your web application is going to be able
to start making authenticated calls to CloudKit.
So to implement authentication on your page, you first have
to provide a location for a sign in button.

So you set a development to give it the ID Apple sign-in button.
Secondly, you have to call the method called set up off,
and this is going to check
for the authentication state of the user.
So if the user is already signed in, a user info object is going
to come back, and that's all you need to look for.

In addition to user info object is going to have a record name
and this is the stable identifier
that we just looked at.

So this stable identifier is going to be the same now
on the web as it is on iOS and OS X so you have a way
of referencing the same user across all of the platforms.

So in addition to checking for authentication state,
you also need to handle what happens
when user signs in or signs out.

So you call when user signs in on the container,
and you get back a promise, and it's going to resolve
as soon as the user signs in.

And it's exactly the same for when the user signs out.
So beyond those default capabilities in CloudKit JS
around authentication.

We also provide toggles and ways
to customize how you handle authentication.
So this next example is showing you how you can actually persist
the AUTH between sessions so CloudKit is not going
to write cookies on your domain so if you want a cookie
to be written to store the AUTH session,
you have to set the persist property
to true in the configuration.
Now, instead of cookies, you might actually want
to store the session in some other way.
So this is showing you a couple of hooks in the configuration.
So we have a put token and a get token method and these are going
to get called anytime for put token anytime cloud JS receives
token from the server.
So one example here might be you want to store the session
in local storage or perhaps you might want to store it
in your own server so you can make server
to server calls based on behalf of the user.

So next let's talk about record operations.
And just like Chris showed you earlier with the JSON.
A record in CloudKit JS is basically an object like this.

So we have a record with a record named task 1.
We have record type tasks,
and we have some metadata fields created and modified
which will contain the user that created and modified the record
as well as the time stamp.
The record change tag, which is the version of this record
for conflict resolution, and then comes all
of your custom fields below
that that you have defined in the schema.

In this example we just have one task name, it's a type string
and the value of buy milk.
Now, obviously you might want to store other types of fields
than strings so this is giving you a comparison
of what those look like compared to iOS and OS X.
So in CloudKit framework we have a string
but in CloudKit JS we just use JavaScript strings.
Same thing for number,
for NS data we use basic code 64 and coded binary.

NS data we have a JavaScript number
which is unit time in milliseconds.
So for the more complex objects like CL location,
we have a location object, and a reference object
and also an asset object, and we ask you to look
in the documentation for how each one of these are defined.

So in terms of creating a record, you can go ahead
and define one of these object literals.
In this example we're just saying record type is tasks
and we have one field task name with a value of buy milk
and you can go ahead and call the save record method
on the database object.

You notice though in this case we didn't actually give it the
record name.
So the record name is unique identifier of a record.

So by not specifying that the server is actually going
to go ahead and generate one for us.
Also we don't specify the string type for this particular field,
so CloudKit JS will do some type inference here
and it will figure out that this value is fully a string
to you have to specify this for all of the basic types we have.

So next we want to talk about queries, and this is going
to work a little bit different on the web
through the JavaScript API.

So on iOS and OS X in foundation framework we have NSPredicate.
And NSPredicate is great but it's not really that natural
for the web and it doesn't really conform well
to the JSON API we are exposing through the web services
so we have something that looks very similar to Java literals
for records in that you just define a query like this.

In this example we are saying record type is tasks
and we call perform query on the database, and we are going
to get back all of the records of type tasks.

Now, you can do something a bit more sophisticated.
So in this next example we are providing some options
to the perform query method.

So we are saying this hard key is task name.
We are only going to get back the task name field
from every record.

We are limiting the result set to ten and we will limit records
in the all task custom zone.
So queries also allow you to go and specify a filter.

So in this next example, we are saying still, you know,
we want to look for record types of tasks but we only want
to get back tasks of priority one.

And we call it perform query
and we get back all task with priority one.
You notice here we are using the equals comparators
and we have a lot more comparators available
and it depends on the field type you are querying on so look
in the field documentation
for where each one of those are defined.
As you saw earlier, we were limiting the result set
and so the question is how do you paginate
through the results.
So this is showing one example of that.
So results limits at 10.

So we will get back the first 10 records
when this promise resolves but there is more coming property
on the response object.

So this is telling us more records
to fetch beyond the 10 we just got
so we can pass the response object back to perform query
and CloudKit JS will do all of the work here for us in terms
of fetching the next set of ten records from where we are.
And in this example we are showing should we can chain
these promises together.
So next assets.
So assets work a little bit differently in CloudKit
than the other field types.
So assets are actually not stored with the record itself,
assets are stored outside in something we call asset storage.

So the record simply has a reference
to the asset and asset storage.
The good news is CloudKit JS handles this seamlessly for you.

In this example we have a web page with input element
and lets users select a file like this one
in the CloudKit catalogue app.

So when a file is selected,
the handle file select function is going to get called,
and all we need to do is just get a reference to the file,
and we can use that as the value
for the asset field we are saving.
So CloudKit JS is here going to do the work for us in terms
of uploading the asset to asset storage and then save the record
in the database with a reference to the asset.
Downloading assets even simpler in that when you are asking
for a field that has an asset, you are going
to get back a download URL.
In this example we are fetching one record, a user record,
and you notice here the value has a download URL property,
and you can go ahead and fetch the bits from there
or maybe use this as the source
of your image element, for instance.
So another great feature of CloudKit is subscriptions
and push notifications.

And all pushes to Apple devices go
through Apple Push Notification Service.
Now, traditionally you had to set
up your own third party server for this to work.
So you had to get your own server with your own certificate
with your own server logic and you had to push,
send pushes through that way.
However, with CloudKit, there is no longer necessary.
You can simply set up CloudKit Subscriptions and these act
like triggers in a database.
So these are going to look for changes in data and send
out pushes accordingly when they happen.

And now with CloudKit JS the web will be another client
in this mix.
So we are going to able to receive the exact same pushes
to the web as we are to iOS and OS X.
So to receive pushes you have to set up subscriptions.
This first example is showing you a zone subscription.

To subscription type is zone, subscription ID is change tasks
and we give is zone ID of all tasks.
I would go ahead and save the subscription with the database.

So this will start looking for changes
so any time something changes in the all tasks custom zone.
It will send pushes
to all clients connected to the same account.
So subscriptions also allow you to base them on a query
so this next example we are setting up a subscription,
a query subscription that will fire anything that's created,
updated or deleted in the all task custom zone
and then we specify a query so this particular query is
like when we fetch for records any time a task
of priority one is created, updated or deleted,
a push will get sent out and that's all we have to do.

So on the website, you have to implement two things,
first you have to implement register for notifications.
This will go ahead and fetch a token from the server
that we can use with Apple Push Notification Service
and also park the connection
with Apple Push Connection Service.

And secondly, you need to call add notification listener
which is going to get called any time a notification is received
on a web page.

So last, let me cover a few best practices with CloudKit JS.
So as we saw earlier, you should dynamically link
to the CDN hosted version of CloudKit JS.

This is important to you get the latest updates
and security fixes as we make them available
and it also insures a low latency delivery of this asset
through our vast accomplished distribution network
and it's all for free which is great.
Secondly, you should consider loading CloudKit JS
asynchronously on your page.
This is a good suggestion
for any third party library you might load on the web page
and it will avoid any blocking and impact on user experience
and last you want to make sure you handle the request responses
so the new free limits
of CloudKit are really generous including the limits
for requests.
That said you might be retrieving bursts of traffic
to your website, so you want to make sure
that your client is properly backing up.
If it's retrieving requests through all responses.

So you can also look into how it can batch multiple operations
in a single request and we do have a batch API
with CloudKit JS and if you are interested
in topic you should go to the CloudKit tips
and tricks session tomorrow.
They will talk more about the request throttling across all
of CloudKit and not just web specifically.
So that's it.
That's CloudKit JS.

We really look forward to seeing what you are going
to be building with it.
Please stop by the labs with any questions you might have.

And now I will hand it back to Chris.
CHRIS EDSTROM: Thanks Onar.

So in summary, the CloudKit Web Services provide a full parity
interface to interact with your CloudKit data on the web.
They are often on a per container basis.

We handle authentication, metadata storage,
and asset upload and download.
You handle hosting your static assets
and your JavaScript application code.
And finally we have brought you CloudKit JS
to make this as easy as possible.

You can visit us on the web at developer.Apple.com/cloudKit
and for any questions you have you can visit the Apple
Developer Forums or Apple developer technical support.

If you still have questions beyond that you can reach us
at CloudKit@Apple.com.
There are a few related sessions.

We had what's new in CloudKit yesterday which is available
on line and tomorrow as Onar mentioned we have CloudKit tips
and tricks.

I hope to see you there.
And thank you very much.

Looking for something specific? Enter a topic above and jump straight to the good stuff.