[MUSIC] This video is going to cover the simplest iOS persistence API, NSUserDefaults. NSUserDefaults is just a simple key-value storage persistence API. You can store simple values, like strings, numbers, and dates, in NSUserDefaults. And each value is associated with a key, which is just a string that you define to identify the values that you want to load and store. And it works in a very similar way to the dictionary class, except that it is managed by the operating system, and it doesn't get deleted when your app restarts. You don't have to create a file or find a directory for storing your user defaults. There is one provided by the system. For the first video in this module, we're going to look at the NSUserDefaults API. This API lets you store simple values, like strings and numbers, in a simple dictionary, like storage zone. That is persistent when your app is shut down and restarts. So we have a simple project here. This is just based on the single view template provided with Xcode. I have a basic view controller here, and I've added a button and a label. So we're just going to do something very simple with this to demonstrate how NSUserDefaults works. We're going to start when the user hits the button. We're going to set this label to a description of the current date and time. And what we want to happen is when we restart the app, we want to load the most recent date and time from the last time that the user pressed that button. Even if the app has been shut down and restarted. I have a basic view controller here, which has a couple outlets. So it has an outlet to that Date Label and the Update Button here. And it also has an action for that Update Button. Okay, so let's create a method here that will actually set that label with the current date and time. So let's create a simple function here. So you can see that it finds that dateLabel, and sets it to the current date and time. And, before I go on, I'm actually going to switch over to the full screen mode here, so we can see the code more easily. Okay, so we have, here's that function here. Okay, and then let's add a function here for the updateButtonAction here. Let's add a call to that updateDateLabel function. And let's run this app and kind of see how that works, just very briefly. And you probably can imagine, we're going to hit that button. It's going to show the current date, here we go. So I'm going to hit the button, it shows the current date. And if I shut it down and then restart it, what does it do? It's going to just show that Label, it goes back to being blank again, right? That value of that Label is not persistent across app relaunches, so let's stop that, okay. All right, so what we want to do is have this label remember what the date should be. So in this case, what we're going to do is replace this with a call to NSUserDefaults, to actually save the date and time whenever that button is tapped. Let's see here, let's go here. Okay, so here's this code, it gets the current date. And now it's going to actually use the NSUserDefaults to store that date. So NSUserDefaults has a class method that lets you get the kind of global UserDefaults object. And on that object, you can set and read objects to and from that object, using the setObject and objectForKey methods. So right now, we're just going to set an object on that, and we're going to give it a key. And the key is just a string, so it's just a string that we've chosen. And the object that we're setting is that date. So we can set a date object directly into the NSUserDefaults dictionary. And then we're going to call that updateLabel again. So right now, that updateLabel is only reading the current date and time. So that's not really reading from that stored default. We're going to change that around, let's change that to, [SOUND] DateLabel2, okay, so what it does is it's going to read that object. So it's going to use that objectForKey method. We're going to look it up, using that same string. And it's going to cast it to an NSDate. So the reason for the cast is that NSUserDefaults doesn't necessarily know what types of objects are going to be stored under each key. It's pretty arbitrary, so, one day, it could be a string stored under this, and another day, it could be NSDate. I wouldn't recommend you design your app to work like that. But, in general, it's so flexible that it doesn't know exactly what kind of object it's going to get back. So it's going to cast it to an NSDate object. And here's a pattern that we're going to see a lot when we access arbitrary data. Is that we're going to have to check for nil, just to make sure that it did find an NSDate. If it doesn't find an object under that key, for example, if it was never previously set, it's going to return nil. So we just have to make sure that we check for nil. Once it gets that, it's going to have a date, for sure. And it's going to set that previously stored date to the dateLabels.text. Otherwise, it's going to just put in some default text in there. Okay, so you can see how that works. Let's build and run. Okay, so let's see here. Yes, there's one more thing I forgot to do. You can see that it's set as a label. The last thing we have to do is call that updateLabel in our viewDidLoad here. Let's see here, updateLabel, okay. There we go, this should work. All right, so now we're getting that default text. So the first time it runs and looks for that value, it's not finding it because we haven't set it previously. We haven't clicked on this button since before, so we'll click on the button here. Now we have our current date and time. You'll notice this is in GMT, so it'll be 30 minutes past midnight, and 49 seconds. So if I stop that and run it again, It's loaded that exact same time back in. And if I hit the button, we're getting now a new time every time I hit the button. So it's persisting that data to the NSUserDefaults storage zone. Just a reminder that you can really only set these simple objects in keys. You don't want to put images in there, you don't want to put huge arrays of items. This is really just for persisting bits of state of your app between launches. So maybe the font size that the user has selected, or the color that they want, or the current state of some kind of interactive element of your app. Not really for storing documents or anything like that. NSUserDefaults lets you store and retrieve data within your app. But it also let's you communicate with the Settings app to store and retrieve settings that the user has selected for your app. So, in case you're not super familiar with this, in iOS, the Settings app allows you to actually install a page of settings for your own app. So we can see there's a few third party apps in here, like Twitter. And then if you click on it, you can change some settings for that particular app. Let's add a settings page for our app, that will let the user select from a list of feeds. And when the user selects that feed, we're going to eventually download images for that particular feed. So that they can select from different types of images. And it's going to allow us to show how the NSUserDefaults works with the settings system. So to create a settings page for our app, we're going to just add a settings bundle. So I'm going to highlight the info.plist here. At the bottom and it doesn't really matter. I'm just going to highlight this because it's near the bottom of my list of items in my project. And click New File. And under Resources, so under iOS and look at resource. It's called Settings Bundle. So it looks like a bit of a Lego thing here, and it's called Settings Bundle. Then I click next, and just choose the default name. Click create. And, it loads our Settings Bundle into our project. Now this Settings Bundle is, it has a few default settings, items in it. And everything that you're going to do in this project here is going to be loaded under the root.plist file that's within the Settings Bundle. So if I run this, we can actually see what it installs just by default. So it's running, and we have it up and running. So I can actually go in here, open up settings, and I can see that now it's loaded a row from my photos feed. And I click on that. And we'll see that it's actually got a few different widgets here. So, it's got a switch and it's got a slider, and it's got a text field, and a group. So, what we can do, we're going to customize that to load, to have a multi-selector for the different feeds that we want. Okay, so let's stop that. And I'm just going to sort of force the settings to close so that it works when we restart it. Okay, so here we go. We have our plist here. Now, the thing about this plist is that's it actually is responsible for telling settings what user interface widgets to display. You don't actually use a storyboard or a user interface design file. You actually tell a list of items under the plist file, the root.plist file, and it will show them. So you get special types of lines for each type of object. So you can see there's a text field, toggle switch, slider and they each have sort of sub properties underneath of them. So this is kind of like the info.plist file in terms of the sort of type of data you can store in it. You know, have strings and booleans, and arrays but it's called the root.plist file. Okay, so let me just close all that stuff up. And we're going to just delete those ones that we don't want. We're going to keep the group, and I'm just going to click on the right-hand side to highlight each of this second row, the Text Field name row. And I'm going to delete. Press the delete key on my keyboard, and there we go. Okay, so we have a group. What we're going to do now is just click on this preference items row just on the right-hand side here. Right click, and then do Add Row, and that's going to add another sub items under preference items. And I'm going to select Multi Value. So multi value is a type of item where if the user selects it then the, it sort of gives them a list of items that they can choose from with titles and values associated with each of those items. You'll see in a second how that works. Like I said, there are other items you can add in, sliders, text fields, but if we want to select from a pre-defined list of feeds, multi item I think is the best choice here. So I'm just going to also highlight this group thing again and just drag that up to the top there under preference items so it's first. Okay, so we have multi item here. It has several sub feeds. The first one is the one that we've already selected, the types. So, the type is multi value. The next one is title, so this is the title that is shown when you look at it on the screen, it tells the user what type of option they're selecting from. So we'll just call this Search Tags. So each of our feeds is going to be related to a specific search tag for a specific type of images. And then under, the next one, we have identifier, that's another string. And this identifier option is actually very important because this is the key that NSUserDefaults uses to store and retrieve these settings value. So identifier is what we actually use in our apps. So I'm going to give an identifier that we'll use later in our app. We'll just call it PhotoURLString, and default value, we're going to come back to that in a second. So, let's just go here and add another row. We're going to click the plus sign beside default value, and now it's going to ask us for titles. So titles is an array, and each of these titles is going to be the title that the user sees in the app. So let's show the user what tag they're going to be selecting when they hit one of these option here. So just press enter, and item zero, we'll just call it Kittens. So if the user wants to see kittens they can select this option. The next one will be Pugs. And then the last one we'll use is PIzza. Okay, so those are just the titles that the user sees. It's not the value that we get back into our apps. So what we're going to do is close that up and add one more and that's going to be value. So this is what our app actually see's when the user selects one of this options and again it's another array. So again for this you can add different types of values, you can add an array of strings, you can add numbers or booleans, whatever you want. What we're actually going to do is add some URLs and I've actually pre-programmed them here. So I'm going to drag them in but you could type them in yourself. They're also in that source file online so you can download it. You don't have to actually try and see what's on the screen here. So let me just drag that in, drag in all three of those. So each of these URLs is based on the Flickr API, so it just calls a feed and downloads a list of images in JSON format for a specific search tag. So if users are uploading photos to Flickr and they're using the tag kitten, it'll download photos that have that tag. So the same for pug and the same for pizza. So you can have some fun with this, put in whatever tags you want. And you can play with that later if you want. Okay, so we have our values, and now we can see what we should put in as default values. So the default value is not one of the titles. It's actually one of the values. So we'll choose this first one as the default one. So I'll just, let's see if the best way to do that is to delete that. I think I just easily just drag this in, or you can just enter it on the keyboard. So we'll do that. And I'll set this to default value. And we're going to replace that blank one. Okay. So, we've chosen a default value. Now, this default value is not the default value that our app is going to see. It's actually the default thing that's going to be checked for the user when they load the settings app if they haven't selected anything else yet. So to have a default in our app in a second, we're going to actually, we're going to actually use a different API to set the default value for our app. Okay, so let's run this and see if we can see how that looks in the settings app now. So our app is running, so it should have installed that new settings page. I go down here, I go to PhotoFeed, and now I can see that I have PhotoFeed as my app title, and then I have the Search Tag. And you can see I have my three different titles here that I put in. When I click on one of these titles, the settings app is going to store the related value in the NSUserDefaults dictionary using the identifier that we've selected. Okay, all right, and one last thing. I'm just going to set the title for that group so that the user can see a little bit more context for what they're selecting. So let's just call it, there we go. So you can group multiple settings under the same thing. So we'll just go on to the next thing here. Okay, so let's add some code into our app to actually find that default that the user has set and show the value. We'll just print it out for now. So I'm going to go in here under applicationDidBecomeActive. This is called every time the app is launched or is switched back into from another multitasking app. So I'm just going to add just a quick method here. Okay, let's see, applicationDidBecomeActive. All right, so here we are. We're using NSUserDefaults again, and we're using the standard global defaults and we are going to go in and use that same key that we typed in under the identifier in the settings bundle. And this time, we're just going to print out whatever string we get. So let's run that. We're running it. Just waiting for it to start up. Okay, so we've started it up and we see here under what's been printed out, it's actually giving us nil. And I just discovered what the reason for that is, is that I've created a key here under the, let's see here. Okay, so under the we've used this photo URL string as the original identifier. But under here, if I go back to the app delegate, I actually kind of used a slightly different string for that key, so it's not finding that value. So I'm just going to copy that. Let's fix that. This is actually good, because it's going to allow us to show one more thing. So I'll stop that and then we fix the identifier, let's restart it. Okay and we're still getting nil but this time the reason is that the app doesn't have a default value. So we didn't actually go in to the settings and play around with the settings this time with that new identifier, it's not available in the app now. When we were playing around with it previously, we had that old identifier and it was setting it under I think photo url string. But now that we're using that slightly different identifier, it doesn't have a value for that. Remember, this default value doesn't apply to the app. It only applies to the Settings app. So, we can actually register a default here so that we know that whenever we look for a string for this particular key, it'll actually give us something that we're expecting. So I can actually add that, a good place to do that is right initially in the didfinishlaunchingwithOptions, we know that it'll always run first before any of our other stuff does. So let me just go in here, okay, it finished launching. Okay so this will allow us to kind of demonstrate how this API works. So what we can do is again find that standard global user defaults object and this time we can actually register what we want to have as the default value for a particular key. So we're going to use that PhotoFeedURL string key and then we're going to have this value here. That's going to be the default value that our app is going to get if no one has ever set that particular key. So you remember previously, when we were playing around with the settings, we were using doing a slightly different key. This time nothing has ever been set for this key. The user has never changed it. So this time what we should get is this kittens tags feed URL this time. So let's run it, and instead of printing nil, it should print out. So it's running and the first thing it prints out is that kittens tag thing here. So what we can do next is take a look at what happens when we actually switch into the settings app. I'm going to go down here, see we have our search tags here. Right now, it's set to kittens. I can actually change it to pugs and go back and you can see this time it's printed out pug. So our app is aware now of the settings that the user is selecting when they switch back and forth. Okay, so that's a very simple way to allow the user to customize your app. It's pretty simple because also you don't have to lay out a whole user interface for that. You can just use a P list file and tell the settings app what widgets you want to have and what identifiers I need to map to for the NS user defaults. So in the next session, we're going to take this a little bit further, so we're actually going to modify the user interface a bit and start looking at how to load data into your app from these URLs. Thank you.