Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: tech-talks-2011-3
$eventId
ID of event: tech-talks
$eventContentId
ID of session without event part: 2011-3
$eventShortId
Shortened ID of event: tech-talks
$year
Year of session: 2011
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2012] [Tech Talk World Tour] Ad...

iOS 5 Tech Talk World Tour #3

Adopting iCloud Storage — Part 2

2011 • 41:18

iCloud Storage enables your apps to keep user documents and data in iCloud, so your users can access the same content from all their computers and iOS devices. Dive deeper into the practical tips and techniques for integrating iCloud Storage into your app. Discover how your Core Data app can store its data in iCloud, and understand how to store and retrieve individual files.

Speaker: Michael Jurewitz

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Hello and welcome to Adopting iCloud Storage — Part 2. I'm Michael Jurewitz, the evangelist responsible for iCloud. iCloud Storage is a powerful set of APIs for storing user documents and data in iCloud. By using iCloud, you can make sure that your users' data is available on all of their devices, providing a seamless user experience.

In Part 1, we took a look at the fundamentals of working with iCloud, and how you can adopt the Key Values Store and UI document. Today, we'll take a look at how you can use Core Data with iCloud. Next, I'll show you how your application can store and manage individual files in iCloud. And finally, we'll talk about some tips and tricks that everyone who works with iCloud should know about. So let's get started.

Today, we're going to break things up a little bit. First, we're going to talk about integrating iCloud with Core Data. Next, we're going to take a look at working with individual files and data. And finally, we're going to finish things up with taking a look at some iCloud tips and tricks. So let's get started with Core Data.

Now, just as a refresher, let's remind ourselves about the Core Data stack. So remember, in Core Data, you work with things called Managed Object Contexts. You can think of these as basically like the scratch pads for all of the different managed objects that you happen to have in your application. All these objects, of course, have all of their relationships to each other and hold all of your data.

Now, beneath all that is the actual store file, the SQLite file where all this information gets written out. Sitting between these two layers is the NS Persistent Store Coordinator. And, as the name might suggest, its basic job is to coordinate the interactions between these two different layers. So, with that review out of the way, let's keep going.

So Core Data, what can it do for you? Well, the answer is, quite a lot. Core Data gives you automatic persistence, so you don't need to think about how to write your data out. Core Data does that for you. Core Data also can provide you automatic undo management, so you don't need to worry about undo or redo. You can just look. Core Data help you do it.

Core Data also provides validation and error checking, so you can make sure that all of your data remains valid in exactly the way that you expect it. And Core Data also offers seamless merging of iCloud content. In fact, on the iCloud side, it really is a powerful option for you to take advantage of. Core Data allows you to pick up incremental updates and changes to all the information as it comes over from iCloud.

You also have support for external file references, so you can take things like images, movies, sounds, and store them outside of your database while still integrating directly with iCloud. Core Data is also a great option for shoebox-style applications. Think of any application, say like iPhoto or iTunes, where you're managing lots of content or lots of media. Core Data is really well adapted for that kind of use case.

In other words, it also provides automatic merging and updates of your content. And best of all, it's easy to adopt. But perhaps one of the most important reasons that you'd want to consider using Core Data is how it handles differences that come in from iCloud. And it does so using something called a three-way merge. So let's talk a bit about exactly what a three-way merge actually is. So if we start off with some content, say some address book content. Here we've got John Doe with an email address of [email protected].

On one device, if we go and make a change, say like making the first name Johnny, and then on that same device make a change a little bit later, say by changing the last name to Appleseed, that's all well and good. We've only made one change on one device. Now, if on a second device we had made a different change, say like changing the email address to johnny at apple.com, we would actually have a bit of a problem here.

Because of the way that iCloud likes to manage conflicts and fold this information together, if you were using something like UIDocument, you would have had several file conflicts to have to resolve. However, Core Data can look at all of these changes and look back at the ancestor of all of these, the original John Doe, john at apple.com entry, and basically figure out how to fold all of these differences together to just end up with the right result. It really is a powerful way for you to take advantage of iCloud.

Core Data also helps you write less code. It handles all of the basics of iCloud integration for you, so you don't need to worry about working with NS File Coordinator, NS File Presenter, NS Metadata Query, or NS File Version. If any of these classes or protocols are unfamiliar to you, that's okay.

We're going to talk about them a whole bunch a little bit later. So let's look at how Core Data actually integrates with iCloud. As your application writes to its Core Data store file, Core Data is going to automatically create transaction logs for you in your Ubiquiti container. And this is the data that actually moves between devices.

So if we look at how this works, if you save a document, say, on your iPhone by calling NS Managed Object Context "save," this creates a series of transaction logs. These transaction logs go up to iCloud. And then end up getting distributed out to all of the rest of your devices.

Now, on another device, if you also make some edits and call "save," these new transaction logs will get created. They go back up to iCloud. And then they get redistributed out to all of your devices, helping to keep your data up to date. So Core Data is a very useful tool. Now Core Data Transaction Logs are great because they're simple, they're efficient, and they allow for completely recreating your data, because they are a complete history of every single change you've made to your database.

So how do you get started? Well, it turns out it's really easy. There are a couple persistent store options that you need to add to your persistent store, and basically just one notification that you need to make sure that you subscribe to. So the two options you need to add to your store are the NS Persistent Store Ubiquitous Content Name Key — we'll just call this the Name Key from now on — and the NS Persistent Store Ubiquitous Content URL Key, which we'll just call the URL Key. Now the notification that you want to make sure that you subscribe to is the NS Persistent Store Did Import Ubiquitous Content Changes notification.

So let's talk about working with the Name Key and URL Key. Now the Name Key is a required attribute, and basically this is just a way for you to uniquely identify your store file. And the emphasis here is unique. If you have several store files in your application and they all want to use iCloud, you need to make sure they all have different Name Keys.

Now the URL Key basically just indicates where you would like these transaction logs to be saved in your Ubiquiti container. This is not a required key, but we do recommend setting it. So, for example, pick a directory in your Ubiquiti container that you'd like to use, and supply this location as the URL Key.

Now, actually using these keys in practice is pretty straightforward. Anytime you go to create your persistent store, you pass into it an options dictionary. All that you need to do is make sure that you supply entries for the name key and the URL key if you want to use iCloud with your Core Data store.

Here we've provided a unique name, as well as a path to our transaction logs. Now, normally this options dictionary also contains other options. Things like the NS Migrate Persistent Stores Automatically option, or the NS Infer Mapping Model Automatically option. You want to make sure that you keep those in there. And that's really all you have to do. By just supplying those two keys, you've told Core Data everything that it needs to know to begin taking advantage of iCloud.

So let's take a look at how this works. When you're storing these files in your Ubiquiti container, there are a few things that we recommend. First and foremost, we recommend that you create in your Ubiquiti container a folder that ends in .nosync, and that this is where you place your Core Data store file. Now it's important to place your store file here for a number of reasons. One, if the user signs out of iCloud, you want to make sure that that store file stays in your Ubiquiti container.

The second is that you want to make sure that this store file isn't trying to be synced directly to the iCloud servers, and that's what the .nosync extension does at the end of that folder. You'll also notice in your Ubiquiti container that you've got the directory where you asked Core Data to store your transaction logs.

Now, when a change comes in from iCloud, essentially what happens is a new transaction log is added to that directory. Core Data automatically notices this fact, imports that content directly into your store file, and then notifies your application that this content was imported. This gives you a chance to react to that, update your user interface, tell the user, etc.

Now, one of the most interesting things about setting up your Core Data storage in this way is that when you go to set up, say, a brand new device, when you first access your Ubiquiti container, you'll find that there are a bunch of transaction logs there. But you won't have an existing Core Data store file. Well, Core Data can specifically notice this case, and when you go to create your store file for the first time, it'll actually read in any existing transaction logs and automatically recreate that store file for you, complete with its content.

So let's take a look at how to deal with changes that come in from iCloud. I mentioned before that there's this NS Persistence Store Did Import Ubiquitous Content Changes notification. And this is going to be the notification that Core Data calls anytime there's new content that's come in from iCloud. Your application wants to watch for this notification and make sure that it merges any changes into your managed object context. This is also the perfect opportunity for you to ask any views that might be affected by these changes to refresh their content.

Now, this notification that comes in also has a lot of information passed along with it. In particular, the notification object will identify the specific persistent store that was affected by this import. So if you have multiple stores in your application, you'll know exactly which one updated. The User Info Dictionary also includes a lot of other useful information, in case you need to make use of that in your application. You'll get a chance to know which objects were inserted — so basically which ones were created — which objects were updated, and which objects were deleted.

Now, when merging changes from iCloud, you simply want to write some code that looks a little bit like this: You've subscribed to the NS Persistent Store Did Import Ubiquitous Content Changes notification. And when your notification gets called, you want to turn right back around, and on your Manage Object Context, you want to call "Merge Changes from Context Did Save Notification" and just pass in the notification object. Core Data will take care of the rest. It'll look at what's changed, and make sure that your Managed Object Context reflects that information.

After you've done that, you want to make sure that you give the rest of your application a chance to respond to these changes. In this case, we're creating our own notification, just called "Refresh All Views," and we're posting that within our application. Any of our view controllers that happen to be on screen would want to listen for this notification, and then potentially go and refresh their content.

Now, when it comes to merging content from iCloud, we have some recommendations on how you should do that. The first is to make sure that you have a merge policy set on your Managed Object context. So, what is a merge policy? Well, as you're going and you're changing content in your Managed Object context, when you go to save, that context is going to look at your database, and it's going to look at the state of the information in that database. And if it can tell that it looks like things may have changed out from under you while you're manipulating all the information in memory, by default, Core Data will throw an error.

Now, in the case of iCloud, this is exactly what happens when new content comes in from iCloud. Core Data updates the database automatically underneath you. So, you're not going to want to use something like the default merge policy, which is the error merge policy. In this case, case, when you go to save, you'll just get an error that comes back.

Instead, we recommend setting the NS Merge by Property Object Trump Merge Policy. Now, you might be saying, "Wait, what does that mean again?" Well, let's kind of break this down, because it's actually a little more straightforward than it might seem. So, Merge by Property. What this is saying is, as your Managed Object Context goes to save, it should take a look at every single object that is changed, and check it against its state in the database, property by property, as opposed to, say, only looking at the entire object.

Now, Object Trump. What this means is that the state of the object in memory is what should win. Now, this makes sense. This is usually what the user has most recently ended up changing. So, you want that data to be saved to your database. The opposite of this is the Store Trump Merge Policy. So, again, we recommend setting Merge by Property Object Trump Merge Policy.

Now, when it comes to managing multiple versions of your application, you basically do that like you always have with Core Data. You want to make sure that you provide version information in your Core Data model file like you always have. So we scope your transaction logs based on the version information in your Core Data model file.

Now, the important part here is that all this information remains scoped. So, for example, if you have an app that updates on one device, we'll make sure that all of those transaction logs are written into a directory specific to that app version. Now, on a second device, when the user, say, upgrades your app at a much later time, we'll notice this and we'll automatically migrate in any existing transaction logs from that version of your application that happened to be on iCloud.

You still, though, want to consider some way to detect device differences in your app version. For example, you really don't want to have your app on an iPad and your app on the iPhone be two different versions for a long period of time. If your apps aren't able to successfully talk to each other, that could end up being a bad situation.

So, you might use something like the Key Values Store to simply write the greatest known version of your app. And if you notice that the user's been using an old version of your app for a long period of time, you might want to tell them, hey, there's an update. You should probably go grab that.

Now, Core Data has support for something called External File References that's new in iOS 5, and the upshot is basically that you want to be using them. External File References make it easy to stop storing bindings. So, you can store your binary data and files in your database. Best of all, Core Data handles these seamlessly for iCloud as well.

All it is is a simple checkbox in the Core Data Modeler, and then Core Data will automatically take any of the data you write to these attributes, persist them to the file system, and make sure they make their way up to iCloud. So, let's talk about some tips and tricks for working with Core Data and iCloud.

First and foremost, make sure you place your store file in your Ubiquiti container, but within a directory that ends in .nosync. You want to make sure that your Core Data store file is not directly syncing with the iCloud servers. The next is to use External File References. This is a fantastic feature, and it's a great way for you to keep your database performance more efficient.

Finally, you want to make sure that you let iCloud content be iCloud content. So what does this mean? Well, it's tempting to want to do things like mirror your Core Data database locally so that if a user signs out, they still have access to it. But that really ends up only creating more problems than it solves.

What do you do when the user has signed out for a long period of time and now has different content than what was actually on the cloud? How do you detect this scenario, and how do you solve it? Michael Jurewitz Really, the cleanest thing is to simply treat the user signing out of iCloud as being just that — that they've signed out, and that all of their iCloud content should simply stay there. Let them go ahead and work with local content, but don't mix and match the two. Alright, so that's Core Data. Next, let's talk about working with individual files and data.

So, UI Document and Core Data do a lot of work for you. They handle reading your data, writing your data, updating from iCloud, and coordinating with iCloud. But perhaps you've got an app that just needs a bit more control. Or maybe you have lots of files and data that don't really fit a document model, or even a database model. Well, the good news is, iCloud can still support what you want to do. Let's talk a bit more about that.

So, fundamentally, you've got your app and your Ubiquiti container, and the files that you'd like to put there. But there's a very big problem that you need some help in solving. So, there are going to be changes that come in from other devices to iCloud. iCloud is going to want to update files in your Ubiquiti container.

Your app needs to be able to notice these changes and then indicate those to the user in some way. At the same time, the user is going to be actually using your application, making changes to these files. You're going to want to save those files out, and have iCloud notice those, and then send those out to other devices.

But fundamentally, now you're talking about multiple processes trying to access the same file at the same time. One process trying to write, while another is trying to read, is bad. How does your app know when it's safe to either read or write to these files? iCloud is going to make changes to these files, and then your app has to know that it needs to go read them.

How does your app know when it's time for it to notice these changes? iCloud also needs your files to be up-to-date on disk, so it can do conflict detection. So how does your application know when it needs to write out the newest version of a file? Now, throughout all of this, UIDocument and Core Data handle all of this complexity for you.

So before you go and decide that these are all problems that you want to solve, again, ask yourself, would you just be better served working with UIDocument or with Core Data? Now, if you do want to manage your own files and data, there are some new API as part of iOS 5 that you can take advantage of. The first is a new class called NSFileCoordinator. The second is a protocol called NSFilePresenter.

NSFileCoordinator helps you handle reading and writing in a coordinated fashion, and we'll talk a bit more about what that means in a moment. NSFilePresenter is how you can be notified about changes to the files that you care about. So let's talk about file coordination. Fundamentally, NSFileCoordinator is a locking mechanism. File coordination is basically meant to prevent one process from reading while another process writes. But it's also a notification mechanism.

Any writing that you might do to the file system may cause some other process, such as iCloud, to read. Any reading that you want to do may cause some other process to want to write out new files. want to write out new data for you and vice versa.

So when should you use File Coordinator? Well, anytime that you're trying to do reading, creating, exporting, updating, copying, moving and renaming, even for directories. And did I mention that UIDocument does all of this for you? Now, when do you not need to use NS File Coordinator? Well, the whole point of file coordination is to use it any time you're dealing with content in your Ubiquiti container, so that iCloud can know about the changes that you make, and vice versa.

So, for any content that isn't in your Ubiquiti container, you don't need to use file coordinator. So this includes temporary files, cache files, other files in your application sandbox, etc. So what are the locking rules that file coordinator uses? It's actually pretty straightforward. Readers don't block other readers. If you have two processors trying to read the same file, that's totally safe. Readers do block writers. If you're in the process of reading a file, someone else who wants to update it needs to wait until you're finished reading.

Writers block readers. Again, if you're writing to a file, someone else needs to wait to read that file until you're finished. Writers block other writers. This is to help make sure that two different processes don't just end up creating a bundle of random bits on disk. So writers need to wait for each other to finish before they can write again.

Now, we treat file packages atomically, so the entire file package gets updated or read any time we read or write. And it's important to know that file coordinators don't block themselves, so you don't have to worry about file coordinators deadlocking. So how do you actually create a file coordinator? Well, you do that with a method called "initWithFilePresenters," a method on NS File Coordinator.

You can pass in an NS File Presenter to this method, or nil if you want. Typically, this is the class that is trying to have the reading or writing done on behalf of it. This also helps us filter out messages about your own file access. If we notice that a particular one of your classes is trying to read or write to a file, we won't notify it about that file changing as a result of its own reads or writes. This also helps us break any potential deadlocks, because now we know the different parts of your applications and the files they may be trying to read or write to. So let's take a look at doing some simple reading and writing with NS File Coordinator.

The methods that you're going to use the most often are these two: Coordinate Reading Item at URL and Coordinate Writing Item at URL. Now you'll notice that both of these methods have an end parameter that's a block. It's this "by" accessor. So what you do is you basically pass in a block that represents the reading or the writing that you want to do, and NS File Coordinator invokes that block.

Now, it's important to note that what gets passed into this block is a new URL. Basically, you tell us where on the file system you want to read or write to. And between now and the time that you actually get to do that reading or writing, we'll try to pay attention to anything that may have caused that file or that location to move or be renamed, and we'll pass in a new URL that still points to a valid location. So you want to make sure that you're using this new URL.

Now, it's important to note that both of these methods are synchronous, so you want to make sure that you execute them as part of something like Dispatch Async. So let's take a look at a simple example of reading a file. Here we've got a method called ReadFromURLError. Now the first thing we do is create a file coordinator. So NSFileCoordinator, ALEC, "init with file presenter," and we pass in "self" because we are the object that is trying to do this reading.

Next, we simply call coordinateReadingItemAtURL, we pass in the URL we want to read, and we pass in the block representing the reading that we want to be done. You'll notice this block takes that new URL parameter, and all we're doing is creating a NSData and initing it with a contents of that new URL.

This is going to go ahead and load in that data, and then later we can simply return that data back out to our caller. Now, there's a very important detail here. You'll notice that we declared this NSDataLocal with __Block. What this does is make sure that this data local is actually passed into this block by reference, as opposed to by copy.

This way, when we write information to this data variable as part of this block, we still have that information available to us outside of the block, which is why we can go ahead and just return that data. You also want to make sure along the way that you propagate any error parameters that you might have. So you notice we took in an error parameter, and we made sure that we propagated that on down the stack.

So what might have just happened as we were trying to do that reading? Well, we may have had to wait for other writers. Say, for example, iCloud may have been trying to write to that file. We would have had to wait for that writing to finish. The file might have been moved or deleted, and we would have to be able to handle that circumstance. There would have been NS File Presenter messaging going on. We'll talk more about that in a bit. And there may have been errors that we needed to handle. For example, a file presenter might have had trouble updating.

Let's talk about some other file coordinator API. There's API for doing multiple file coordination. Say, for example, reading at a URL and writing at a URL, all as part of the same action. You would use this typically for things like copies or moves. You'll notice that in each case, you pass in the URL that you want to read from, and the URL that you want to write to. As a difference, the "by accessor" block also takes two URL parameters — basically a new reading URL and a new writing URL. You would want to make sure that you use those parameters as part of your block that's doing that reading and that writing.

NS File Coordinator also has a way for you to do batched file coordination. Now, let's say that you had thousands of files that you knew that you needed to either read from or write to, or possibly both. Well, you can use the "Prepare for Reading Items at URLs" method to be able to do that. In each case, you pass in an array of the URLs that you want to work with.

At the end of this, you're going to be passed back a completion handler, and the expectation is that you are going to invoke this completion handler. This is going to be what allows the system to basically catch up with all the reading and the writing that you just finished doing.

Alright, so let's talk a bit about NS File Presenter. NS File Presenter is how you can find out what's happening with the files that you care about. Your app basically gets a chance to say what files it happens to be showing to the user. Now, as a result, your application also gets to participate in other processes' coordinated file access to those particular files.

Now, when should you be an NSFile presenter? Well, anytime that you're showing an item to the user for viewing or editing, you likely want to be a file presenter for that file. This could be a file, a file package, or even a directory of files. This is going to give your application an opportunity to reload its state for a file anytime that file happens to change. It's also going to give your application the opportunity to close that file if another process happens to delete it.

And one of the things you're going to frequently do when you're a file presenter is have to relinquish control of that file to another process for a short period of time. Now, for all of this, these are things that UIDocument does for you. So again, if you can use something like UIDocument, there's a lot of value in doing so.

Now, NSFilePresenter, again, is a protocol. So you get a chance to implement methods on your own classes, like "Presented Item Did Change," "Presented Item Did Move to URL," etc. And this is how your classes will be notified when these particular events happen. You also get an opportunity to be told when you need to do certain things in the lifecycle of your file. Save, for example, when you really need to save that most current version of your file right now. Or perhaps that you need to accommodate the fact that another process just deleted that file.

So again, remember, it's a protocol, not a class. And you become a file presenter by using a couple methods on things like NSFileCoordinator. So NSFileCoordinator has a method called AddFilePresenter and RemoveFilePresenter. There's also the InitWithFilePresenter that we saw earlier. Now you need to make sure whenever you add yourself as a file presenter that you also remove yourself as a file presenter once you're done. Oftentimes, dialog is too late. You want to be doing this sooner. As an example, UIDocument does this in close with Completion Handler, so you should be doing the same for your own files and documents.

Now, occasionally you need to be able to relinquish your file to other readers and writers, and there's a couple methods that'll get called when this exactly needs to happen. So you've got Relinquish Presented Item to Reader and Relinquish Presented Item to Writer. These get called basically when someone else wants to read or write to this file that you care about.

Now, what gets passed into this method is sort of this crazy-looking block parameter, and we'll try to break down exactly what it is that's getting passed in here. The upshot is that what's getting passed in is a block that you need to quickly invoke. You also get a chance to pass your own block back into this method that represents any sort of work that you want to be done immediately after that reading or writing takes place. So let's look at an example.

So here we have a sample implementation of relinquishPresentedItemToWriter. So the first thing you want to do when implementing a method like this, when it gets called, is make sure that you stop looking at the file that's about to be written to. You want to make sure that you stop looking at any IVARs that might relate to that file. Basically, stop paying attention to it for that moment in time.

The very next thing that you need to do is make sure that you invoke that writer block that gets passed in. Again, this is the actual unit of writing that is about to happen to this file. This is your chance to basically let the other process go, and you have to do this.

Now, at the same time, though, you also get a chance to pass in your own block that represents the additional work that you want done once that writing is finished. So here we're passing in our own block that basically is just going to tell ourselves to stop waiting for this writer. And once that writing is finished, that will be invoked, and we go back to normal using that file.

Now, whenever you're a file presenter, you're going to most commonly see things like "Presented item did change" or possibly "Presented item did move to URL" get called on your file presenter. This is going to be what tells you that a change actually happened, and it's your opportunity to catch up, to notice this change, to update your UI. Typically, this is going to happen while you happen to be relinquished to a writer. This is going to be your opportunity to notice that change and make sure that all of your state is up to date.

All right, so that's a bit about working with files and data with iCloud. Finally, let's take a look at some tips and tricks for working with iCloud. So first and foremost, where do your files go? Where exactly should you put them within the Ubiquiti container itself? The Ubiquiti container is just this normal directory, and you can put things really wherever you want. There is, however, one special directory, and that's the Documents directory. Now, this directory doesn't exist by default, but if you create it and you store files into that folder, then users can actually view the file names of the items in that directory in their iCloud Storage settings.

What's more, users also have the ability to individually delete items in that directory. So if you have items that you don't intend for the user to be able to individually delete, you probably don't want to put them there. You can also create any other directories you want in your Ubiquiti container to suit your needs. These won't show up to the user, and they only get listed basically as files and data.

So how should you move a file to your Ubiquiti container? Say you've got a file in your application sandbox, what do you do? How do you properly move that over? Well, NS File Manager has a method called Set Ubiquitous Item at URL Destination URL Error. So all you need to do is basically call Set Ubiquitous Yes, pass in the URL to where the file currently exists in your application sandbox, and then pass in the URL in your Ubiquiti container where you want this file to end up.

NS File Manager will move this file in a coordinated fashion, but you need to make sure that you create any intermediary directories that you wanted ahead of time. Now it's important to note that this method blocks, so you'll want to make sure that you call this asynchronously, typically via something like Dispatch Async.

When you want to move files out of your Ubiquiti container, you do something rather similar. You can think of this as basically wanting to download an item and make a local copy of it. In this case, you still use Set Ubiquitous Item at URL Destination URL, but in this case, you pass in Set Ubiquitous No, and you give the path to the item in your Ubiquiti container as the item at URL, and as the destination URL, you give some path into your application sandbox. sandbox.

Now, as you work with iCloud, your users are potentially going to be creating lots of files. And really, you should try to endeavor to help them not waste disk space. You want to evict infrequently used files. The way to think about this is that any file that is actually in your Ubiquiti container is also being stored in iCloud.

So if you see a file that the user has not accessed in, say, a few weeks or a few months, you can go ahead and call evict ubiquitous item at URL on that particular file. This is a method on NS File Manager, and what this will do is basically remove the local copy of that file, but leave the copy on iCloud intact. hacked, so you can go and download that the next time you need it.

One of the coolest features in iCloud is the ability to publish an item for sharing with other users. In this case, NS File Manager has a method called URL for Publishing Ubiquitous Item at URL . What this allows you to do is take any file in your Ubiquiti container, publish it to the iCloud servers, and then get back a URL that you can send to other users who want to download a copy. The important part here is that they are downloading a copy of the file.

This is not, say, the same reference to the same file for everyone to share. This is simply the ability for them to download a copy. The important part here is that they are downloading a copy of the file. This is not, say, the same reference to the same file for everyone to share.

This is simply the ability for them to download a copy. Now, when it comes to telling the state of a file, NSURL has a lot of help to provide. You might, for example, want to be able to show the user that a file is uploading or downloading or what percent it may be complete. And so, NSURL has a method called Resource Values for Keys.

And there are a bunch of new keys to find for working with iCloud. So for example, for a given item, you can find out: Is it downloaded? Is it downloading? Is it finished going either up or down? This gives you a chance to provide up-to-date user interfaces so your users know exactly what's going on with their files.

All right, so we talked about working with Core Data as well as working with individual files and data. Okay, so you saw how your Core Data app can work with iCloud, discovered how your app can manage individual files and data and store them to iCloud, and you learned the tips and tricks to use iCloud to its fullest. I look forward to seeing the great apps that you'll build that use iCloud Storage.