0 1 00:00:01,030 --> 00:00:07,150 Now, through your journey as an iOS developer, inevitably, you will come across UserDefaults 1 2 00:00:07,150 --> 00:00:12,970 and you'll probably use it in quite a few of your projects because it's really simple to use, very flexible, and 2 3 00:00:12,970 --> 00:00:15,670 doesn't take very many lines of code. 3 4 00:00:15,670 --> 00:00:19,200 Now, let's have a look at some of the things that you can do with UserDefaults. 4 5 00:00:19,480 --> 00:00:22,750 Let's establish a default and we'll call it-- 5 6 00:00:22,750 --> 00:00:28,960 Now, remember, when you create property names or variable names, you can't call it certain words like default 6 7 00:00:29,290 --> 00:00:33,660 or class, and you can tell because it highlights it in a different color 7 8 00:00:33,670 --> 00:00:40,300 in this sort of pinkish color that tells you that this is a keyword that's reserved for certain uses. 8 9 00:00:40,330 --> 00:00:48,730 So let's create a new UserDefault called defaults and we'll set it to equal UserDefaults.standard. 9 10 00:00:48,830 --> 00:00:54,880 And let's see what are some of the things that we can set into our UserDefaults. So we can write something 10 11 00:00:54,880 --> 00:01:02,430 like set URL forKey, set value, which is type optional any key, 11 12 00:01:02,440 --> 00:01:08,580 so we can use optionals. We can set Booleans, doubles, floats, integers. 12 13 00:01:08,580 --> 00:01:15,070 So one of the scenarios that you might find yourself using UserDefault is saving user preferences inside 13 14 00:01:15,070 --> 00:01:16,070 your app. 14 15 00:01:16,090 --> 00:01:22,120 So, for example, if you had an app where you allow the user to set the music volume, you might say something 15 16 00:01:22,120 --> 00:01:31,060 like set 0.24 forKey volume, and that means that at a later date, you can say, 16 17 00:01:31,360 --> 00:01:40,230 let volume = defaults.float forKey volume. 17 18 00:01:40,600 --> 00:01:47,860 Then you can use that persisted data for volume to always set your games or your app's volume to 18 19 00:01:47,860 --> 00:01:50,230 0.24 which is what the user prefers. 19 20 00:01:50,230 --> 00:01:55,780 Now, aside from floats, you can also use set on Booleans. 20 21 00:01:55,780 --> 00:02:04,180 So, for example, we'll set true for the key "MusicOn, so that every time they open up your game, you always 21 22 00:02:04,180 --> 00:02:08,230 have the music on, the music off depending on their preference. 22 23 00:02:08,500 --> 00:02:11,400 And there's whole bunch of other ones I'm just going to quickly run through. 23 24 00:02:11,620 --> 00:02:15,490 So you can, obviously, set strings, right? 24 25 00:02:17,500 --> 00:02:20,350 So, for example, you might have "PlayerName." 25 26 00:02:20,470 --> 00:02:28,840 You can also track user behavior by using defaults like set, use any, we use the current date by just 26 27 00:02:28,840 --> 00:02:31,650 tapping into a new object of date. 27 28 00:02:31,690 --> 00:02:41,460 And the key is going to be "AppLastOpenedByUser." And you can see that when you try to retrieve this, 28 29 00:02:41,560 --> 00:02:48,650 let appLastOpen = defaults.object. 29 30 00:02:48,680 --> 00:02:53,370 Now, we're using object because we're not trying to grab a float and "in" to a string, 30 31 00:02:53,510 --> 00:02:57,040 we're trying to grab something that was saved using optional "Any." 31 32 00:02:57,110 --> 00:03:03,740 So we should try and get back using the method that grabs us an optional of any data type. 32 33 00:03:03,770 --> 00:03:10,510 So let's hit object forKey and I'm just going to paste that incredibly long key into here. 33 34 00:03:11,030 --> 00:03:19,120 And now, you can see that appLastOpened is set to equal the time when this default was set. 34 35 00:03:19,250 --> 00:03:26,520 And, of course, every single time I run the app, it's going to change that time just by a little bit. 35 36 00:03:26,540 --> 00:03:30,540 Cool. So we've seen some pretty standard data types being saved. 36 37 00:03:30,590 --> 00:03:38,540 Now, if you want to get really fancy with your defaults, you can also save a collections like 37 38 00:03:38,570 --> 00:03:50,970 let array = [1, 2, 3] and we can say defaults set value of optional Any to array, and forKey, 38 39 00:03:50,970 --> 00:03:52,780 let's call it "myArray." 39 40 00:03:53,090 --> 00:04:03,560 And there's a special method that allows you to get that array back by using defaults.array 40 41 00:04:03,560 --> 00:04:07,480 forKey string, and it's going to be "myArray." 41 42 00:04:07,490 --> 00:04:13,580 Now, you can either let Swift infer what's the data type of the object contained inside the array, because 42 43 00:04:13,610 --> 00:04:20,200 if you option-click on this array here, you can see that when we use defaults to retrieve an array 43 44 00:04:20,360 --> 00:04:24,910 out of UseDefaults. The return type is actually an optional array, 44 45 00:04:25,190 --> 00:04:29,300 and it doesn't know what is the data type that's contained inside the array. 45 46 00:04:29,300 --> 00:04:37,850 So if you want to be more explicit, you can downcast the array into an array of integers. And we can do 46 47 00:04:37,850 --> 00:04:44,590 that safely because we saved it here and we should know what the data type is that went into that default 47 48 00:04:44,600 --> 00:04:45,780 for the key "myArray." 48 49 00:04:45,920 --> 00:04:49,580 And similarly, you can do the same thing for dictionaries. 49 50 00:04:51,120 --> 00:04:56,650 And let's just say let dictionary = 50 51 00:04:59,640 --> 00:05:04,350 [name": "Angela"] and we'll say default.set. 51 52 00:05:04,350 --> 00:05:09,060 And, of course, we're using "Any" again, and we're going to put dictionary in there and 52 53 00:05:09,060 --> 00:05:12,040 we'll call it "myDictionary." 53 54 00:05:12,810 --> 00:05:20,150 And then we can retrieve it over here by using defaults.dictionary 54 55 00:05:21,090 --> 00:05:24,280 and we'll put the key back in. 55 56 00:05:24,310 --> 00:05:27,830 Now the spelling of your keys matter a great deal. 56 57 00:05:27,880 --> 00:05:33,670 And if you get the case wrong or if you spell it even slightly wrong, it's probably going to crash your 57 58 00:05:33,670 --> 00:05:34,500 program. 58 59 00:05:34,570 --> 00:05:40,150 So it's usually a good idea to create a constant at the top when you're trying to access these things 59 60 00:05:40,480 --> 00:05:47,020 like, for example, dictionaryKey, and we'll set it to equal "myDictionary." 60 61 00:05:47,020 --> 00:05:54,370 So that way, instead of putting "myDictionary" as a string in all of these places, you can simply use your 61 62 00:05:54,370 --> 00:06:00,040 dictionary key in all the places where you need to access it. 62 63 00:06:00,310 --> 00:06:04,150 And this way if you do need to change your key, then you can do it in one place. 63 64 00:06:04,300 --> 00:06:08,630 And also if you do have any errors, it's much easier to trace and debug. 64 65 00:06:08,630 --> 00:06:08,910 All right. 65 66 00:06:08,920 --> 00:06:12,440 So that's a little bit of an overview of UserDefault 66 67 00:06:12,520 --> 00:06:18,430 and what you can do with them. As you can see, they're really flexible, really adaptable, and that's one 67 68 00:06:18,430 --> 00:06:21,430 of the reasons why they're prone to abuse. 68 69 00:06:21,430 --> 00:06:27,120 Now, you should only really be using UserDefaults to persist small bits of data, 69 70 00:06:27,190 --> 00:06:34,600 anything that's a few kilobytes, like a volume here and there, or a Boolean, or maybe the player names. 70 71 00:06:34,900 --> 00:06:41,470 The danger is once you start getting into saving arrays or dictionaries, that the data starts getting 71 72 00:06:41,530 --> 00:06:45,820 really, really big, really unwieldy and unmanageable. 72 73 00:06:45,820 --> 00:06:52,600 Now, the reason why we say that is because UserDefaults is not a database and it should not be used 73 74 00:06:52,690 --> 00:07:01,720 as a database. As we saw earlier on, all of these key-value pairs get saved into a plist and that entire 74 75 00:07:01,990 --> 00:07:09,820 plist of your UserDefault has to be loaded up synchronously. So, all of it gets loaded up before you can 75 76 00:07:09,850 --> 00:07:13,250 access any of the values contained inside the keys. 76 77 00:07:13,270 --> 00:07:18,370 So that means that if you're looking for something really small like the volume that was saved which 77 78 00:07:18,370 --> 00:07:24,580 is going to be just 0.24 which is a very small piece of data. Even to grab that small piece 78 79 00:07:24,580 --> 00:07:30,640 of data your iPhone or your simulator or whatever device you're running your app on has to load up the 79 80 00:07:30,730 --> 00:07:33,540 entire UserDefaults plist. 80 81 00:07:33,550 --> 00:07:37,100 So everything that you store in it has to be loaded up. 81 82 00:07:37,270 --> 00:07:45,700 And that means that it can be very time consuming if you start saving large bits of data in there. And certainly 82 83 00:07:45,790 --> 00:07:52,000 across the Internet, you'll come across various implementations on StackOverflow or GitHub where people 83 84 00:07:52,000 --> 00:07:57,580 are basically trying to use UserDefaults as a database. But just keep in mind, it's not a database and 84 85 00:07:57,580 --> 00:08:03,490 it shouldn't be used as one because it's going to have significant impact on the efficiency and the 85 86 00:08:03,490 --> 00:08:04,960 speed of your app. 86 87 00:08:04,960 --> 00:08:11,860 Now, one of the things that people always find really mysterious about UserDefaults is, how is it possible 87 88 00:08:12,220 --> 00:08:19,900 that I can simply use UserDefault across all classes and objects and I still get back the same item. 88 89 00:08:19,930 --> 00:08:23,050 And the reason for this is because it's quite special. 89 90 00:08:23,080 --> 00:08:30,420 It's what's known as a singleton. And in the next lesson, I want to show you what singletons are and we'll 90 91 00:08:30,430 --> 00:08:35,770 go to some of the way towards understanding how UserDefault actually works. 91 92 00:08:35,800 --> 00:08:36,740 So I'll see you there.