0 1 00:00:00,800 --> 00:00:01,200 All right. 1 2 00:00:01,220 --> 00:00:08,370 So in the last lesson, we looked at how you can install, setup, and configure Realm to be our method of 2 3 00:00:08,460 --> 00:00:10,260 persisting data. 3 4 00:00:10,260 --> 00:00:16,650 Now, in this lesson, I'm going to delete all of this so that we don't keep adding the same piece of data 4 5 00:00:16,980 --> 00:00:18,780 into our Realm. 5 6 00:00:18,930 --> 00:00:23,420 And I'm also going to delete this try realm.write. 6 7 00:00:23,430 --> 00:00:29,790 Now, I'm going to leave this do-catch block where we initialize our brand-new Realm. And let's not worry too 7 8 00:00:29,790 --> 00:00:32,270 much about these warnings for now. 8 9 00:00:32,310 --> 00:00:40,780 So I'm going to go ahead and delete this Data class that we created that we use as just as an example, 9 10 00:00:40,920 --> 00:00:48,150 and I'm going to replace this Core Data data model with a class called Category and a class called Item. 10 11 00:00:48,150 --> 00:00:53,910 So let's go into our Data Model folder, hit command Nto create a new Swift file 11 12 00:00:53,910 --> 00:00:58,750 and this is going to be called Item and we're going to hit Create, 12 13 00:00:59,100 --> 00:01:05,050 and then I'm going to create another one called Category and hit Create. 13 14 00:01:06,270 --> 00:01:13,440 So now we have both of our entities, or in this case, classes and we're going to use them to represent 14 15 00:01:13,590 --> 00:01:19,140 all the properties and relationships that we've specified inside Core Data. 15 16 00:01:19,140 --> 00:01:28,470 So inside Item, I first have to import Realm Swift in order to use it, and then I'm gonna create a new 16 17 00:01:28,470 --> 00:01:37,050 class called Item and the superclass is going to be a Realm Object. And it's going to have two properties. 17 18 00:01:37,260 --> 00:01:45,030 one which is the title, which is going to be a String, that's going to start off as empty. 18 19 00:01:45,360 --> 00:01:51,440 And the other one is going to be the property done which is going to be a Boolean and this is going 19 20 00:01:51,440 --> 00:01:53,390 to start off as false. 20 21 00:01:53,550 --> 00:02:01,290 And, remember, in order to create properties using Realm, we have to add the @objc modifier and 21 22 00:02:01,380 --> 00:02:04,590 also the dynamic keyword. 22 23 00:02:04,590 --> 00:02:08,600 So let's go ahead and add that to both of our properties. 23 24 00:02:08,640 --> 00:02:15,990 And now this is a complete representation of our item entity using properties instead of attributes. 24 25 00:02:15,990 --> 00:02:23,760 Now, you'll see that it gives you an error saying that this is an invalid redeclaration of Item. 25 26 00:02:23,790 --> 00:02:26,170 So it's saying that there's already a class called Item, 26 27 00:02:26,190 --> 00:02:27,630 but where where is it? 27 28 00:02:27,630 --> 00:02:29,450 I don't see another class called Item. 28 29 00:02:29,610 --> 00:02:31,050 What's going on here? 29 30 00:02:31,050 --> 00:02:35,430 Well, do you remember that we said when you create a new data model using Core Data, 30 31 00:02:35,700 --> 00:02:43,140 If you select the entity and you select Coadegen as Class Definition, then it's going to create a class 31 32 00:02:43,230 --> 00:02:49,440 called Item with these properties, or much the equivalent to that? 32 33 00:02:49,440 --> 00:02:56,370 So you could either select Codegen Manual/None in order to not generate those Class Definitions, or in 33 34 00:02:56,370 --> 00:03:02,220 our case, we're actually just going to delete our Data Model because not going to be the one that we're 34 35 00:03:02,220 --> 00:03:04,370 going to use from now on. 35 36 00:03:04,380 --> 00:03:07,170 So I'm going to right click and hit Delete. 36 37 00:03:08,160 --> 00:03:10,230 So, now it no longer exists, 37 38 00:03:10,320 --> 00:03:16,950 and if we hit command B to build and, essentially, refresh, then that will get rid of that error where it 38 39 00:03:16,950 --> 00:03:20,640 says that this item class is a redeclaration. 39 40 00:03:20,640 --> 00:03:26,520 Now, we'll end up with more errors because, remember, for most of our view controllers, we're using our 40 41 00:03:26,520 --> 00:03:31,890 Core Data NSManagedObjects, and now we're switching it to Realm objects, 41 42 00:03:31,890 --> 00:03:34,550 so there's going to be a little bit of fixing in there. 42 43 00:03:34,710 --> 00:03:38,880 But let's first finish creating our Data Models. 43 44 00:03:38,970 --> 00:03:43,330 So we've done that for item, and now we have to move on to category. 44 45 00:03:43,600 --> 00:03:48,810 And I'm actually going to just change the order here because it's Category then Items, and that makes 45 46 00:03:48,810 --> 00:03:50,460 a little bit more sense to my brain. 46 47 00:03:50,460 --> 00:03:59,850 So as a challenge, I'd like you to set up your Category data model to include a property called name which 47 48 00:03:59,850 --> 00:04:06,930 is going to be of data type string and it's going to start off with the value of an empty string. 48 49 00:04:06,990 --> 00:04:09,140 So go ahead and pause the video and give it a go. 49 50 00:04:11,170 --> 00:04:11,530 All right. 50 51 00:04:11,540 --> 00:04:14,210 So that is pretty simple task. 51 52 00:04:14,210 --> 00:04:20,870 All we have to do in order to use Realm is, of course, import Realm Swift, and then we're going to create 52 53 00:04:20,900 --> 00:04:29,930 a new class that's called Category and it's going to inherit the Object class, and the code in here is 53 54 00:04:29,930 --> 00:04:36,140 going to be an Objective-C modifier and the dynamic keyword, 54 55 00:04:36,140 --> 00:04:39,110 and then we're going to say var name, 55 56 00:04:39,110 --> 00:04:41,680 name of the category, which is going to be a string, 56 57 00:04:41,710 --> 00:04:44,500 and it's going to start off being an empty string. 57 58 00:04:44,540 --> 00:04:44,780 All right. 58 59 00:04:44,810 --> 00:04:45,580 So that's it. 59 60 00:04:45,620 --> 00:04:46,460 That was done. 60 61 00:04:46,460 --> 00:04:47,710 Did you manage to get that? 61 62 00:04:47,810 --> 00:04:56,150 Now, in addition to having these properties, if you remember, our Data model using Core Data also had relationships 62 63 00:04:56,450 --> 00:05:03,350 where we could specify that categories point towards items and items point back to categories. 63 64 00:05:03,350 --> 00:05:07,400 So let's go ahead and see how we can do that using Realm. 64 65 00:05:07,430 --> 00:05:15,890 Now, the forward relationship is the easiest, and it's as simple as creating a constant called items and 65 66 00:05:15,890 --> 00:05:20,510 it's going to be set to a collection type called List. 66 67 00:05:20,510 --> 00:05:22,460 And this is something that comes from Realm. 67 68 00:05:22,550 --> 00:05:28,250 And it's basically a container type just as array or dictionaries are container types. 68 69 00:05:28,310 --> 00:05:33,370 But this is something that they decide called List which is very, very similar to a raise. 69 70 00:05:33,370 --> 00:05:40,580 Now, if we create a new list, we also have to specify what is the data type of the items inside the List 70 71 00:05:40,580 --> 00:05:42,380 or inside the array. 71 72 00:05:42,620 --> 00:05:46,910 And in our case, it's going to be a whole bunch of Item objects. 72 73 00:05:47,030 --> 00:05:54,260 So this syntax may or may not be familiar to you, but when we create new arrays, so let's say, let's create 73 74 00:05:54,290 --> 00:05:58,430 let array equals, I don't know, 1, 2, 3. 74 75 00:05:58,430 --> 00:06:00,650 This is one way of declaring the array, 75 76 00:06:00,680 --> 00:06:03,370 so this uses type inference, 76 77 00:06:03,380 --> 00:06:04,050 right? 77 78 00:06:04,190 --> 00:06:05,660 But the other way of doing it. 78 79 00:06:05,690 --> 00:06:12,040 We could also say that this is an array of integers and we're going to initialize it as an empty array. 79 80 00:06:12,140 --> 00:06:19,070 And the other way still is that we can simply say, the array is going to be of type an array of integers, 80 81 00:06:19,310 --> 00:06:22,000 and it's going to be equal to one two three. 81 82 00:06:22,010 --> 00:06:23,470 That's perfectly valid. 82 83 00:06:23,540 --> 00:06:33,530 Now, a method that we haven't seen so far is we can also declare this as the type Array and say that 83 84 00:06:33,740 --> 00:06:36,650 it is going to contain an array of integers. 84 85 00:06:36,650 --> 00:06:40,220 Now, this and the previous syntax are both valid. 85 86 00:06:40,250 --> 00:06:50,570 So if you wanted to declare a empty array of integers, you could also do it like so by simply initializing 86 87 00:06:50,570 --> 00:06:53,540 it as an empty array of integers. 87 88 00:06:53,540 --> 00:06:56,570 Now, this is exactly what we're going to do here. 88 89 00:06:56,570 --> 00:07:03,530 We're going to create this constant called Items and it's going to hold a list of item objects and we're 89 90 00:07:03,530 --> 00:07:06,600 going to initialize it as an empty list. 90 91 00:07:06,800 --> 00:07:11,510 So I'm just trying to show that this is not some foreign sort of syntax. 91 92 00:07:11,660 --> 00:07:14,000 It's actually something that's perfectly Swifty. 92 93 00:07:14,300 --> 00:07:20,900 And the only thing that's foreign is this class List which is something that comes from our Realm framework. 93 94 00:07:20,900 --> 00:07:28,430 So this, essentially, defines the forward relationship, i.e., inside each Category, 94 95 00:07:28,430 --> 00:07:36,060 there's this thing called items that's going to point to a list of Item objects. 95 96 00:07:36,260 --> 00:07:41,750 Now in Realm, the inverse relationship is not defined automatically. 96 97 00:07:41,750 --> 00:07:46,840 Instead, you actually have to go inside the Item class and create it yourself. 97 98 00:07:46,850 --> 00:07:48,380 So let's do that now. 98 99 00:07:48,410 --> 00:07:56,840 So we called our inverse relationship parentCategory and it's going to be set to an object of the class 99 100 00:07:56,960 --> 00:08:06,260 LinkingObjects. And LinkingObjects are auto-updating containers that represent zero or more objects 100 101 00:08:06,380 --> 00:08:11,090 that are linked to its owning model object through a property relationship. 101 102 00:08:11,090 --> 00:08:17,360 Now that sounds really, really complicated, but it's actually not. It's simply defining the inverse relationship 102 103 00:08:17,510 --> 00:08:18,410 of items. 103 104 00:08:18,410 --> 00:08:27,920 So each category has a one to many relationship with a List of I tems and each item has an inverse relationship 104 105 00:08:28,010 --> 00:08:31,160 to a category called the parentCategory. 105 106 00:08:31,160 --> 00:08:38,000 And we have to initialize LinkingObjects with a type and a property name. 106 107 00:08:38,000 --> 00:08:43,430 So the type is going to be whatever object that we have .type. 107 108 00:08:43,430 --> 00:08:48,100 So if we simply wrote Category, then this is just the class. 108 109 00:08:48,140 --> 00:08:49,910 It's not actually the type. 109 110 00:08:49,910 --> 00:08:54,100 In order to make it the type of Category, we have to say .self. 110 111 00:08:54,170 --> 00:08:56,720 And that becomes the Category type. 111 112 00:08:56,990 --> 00:09:04,580 And then the property that we need to specify is what is the name of that forward relationship which 112 113 00:09:04,580 --> 00:09:06,670 is, of course, items. 113 114 00:09:06,680 --> 00:09:15,310 So all we have to say here is specify a string called "items" that points to the forward relationship. 114 115 00:09:15,310 --> 00:09:18,610 So, now we have the forward relationship, 115 116 00:09:18,730 --> 00:09:25,870 each Category having a list of items. And the reverse category, each item has a parentCategory that is 116 117 00:09:25,870 --> 00:09:27,880 of the type Category 117 118 00:09:27,880 --> 00:09:29,900 and it comes from that property 118 119 00:09:29,910 --> 00:09:30,900 called "items." 119 120 00:09:30,910 --> 00:09:38,350 So now we're ready to go and fix all of these errors and use our Realm data model, instead of our Core 120 121 00:09:38,350 --> 00:09:39,670 Data data model. 121 122 00:09:39,670 --> 00:09:46,220 So let's head over to CategoryViewController and we're going to, first, initialize a new Realm. 122 123 00:09:46,270 --> 00:09:52,300 So we're gonna say let realm = try! to initialize a new Realm. 123 124 00:09:52,300 --> 00:10:00,040 Now I know that we've always been cautious with the exclamation marks, as you should be, but not all cases 124 125 00:10:00,100 --> 00:10:02,710 of try exclamation mark are bad. 125 126 00:10:02,740 --> 00:10:09,940 So this is what you would call a code smell or bad smell, and it's something that indicates or hints 126 127 00:10:10,000 --> 00:10:16,360 at possibly bad code, and maybe a deeper problem, but not always. 127 128 00:10:16,360 --> 00:10:21,610 So just as while you're walking around and you smell something that smells really bad, it could be a dead 128 129 00:10:21,610 --> 00:10:24,490 body or it could be just the trash, 129 130 00:10:24,490 --> 00:10:25,260 right? 130 131 00:10:25,300 --> 00:10:28,320 And in this case, it's actually not an issue. 131 132 00:10:28,360 --> 00:10:36,370 The reason why this initialization throws or can throw an error is because according to Realm, the first 132 133 00:10:36,370 --> 00:10:42,030 time when you're creating a new Realm instance, it can fail if your resources are constrained. 133 134 00:10:42,160 --> 00:10:48,070 But in practice, this can only happen the first time a Realm instance is created on a given thread. 134 135 00:10:48,070 --> 00:10:55,840 So if you look at the Realm documentation, then this is a perfectly valid way of declaring and creating 135 136 00:10:55,900 --> 00:10:56,910 a new Realm. 136 137 00:10:56,920 --> 00:11:02,290 So if you're interested in that, then I'll link to the documentation and you can have a deeper read. 137 138 00:11:03,010 --> 00:11:09,190 Xcode is still giving us this error saying "Use of unresolved identify 'Realm,'" and that is because, 138 139 00:11:09,190 --> 00:11:13,640 of course, that we've got to use Realm, instead of Core Data. 139 140 00:11:13,810 --> 00:11:18,610 So I'm just going to replace that which is going to create more errors for me, 140 141 00:11:18,910 --> 00:11:22,540 but we're going to go and fix those steadily one by one. 141 142 00:11:22,540 --> 00:11:31,870 Let's go into the parts of our code where we create a new piece of data inside our database and that 142 143 00:11:31,870 --> 00:11:38,800 is, of course, inside the addButtonPressed and it's--and more specifically, it's in this closure when 143 144 00:11:38,800 --> 00:11:42,520 we press the Add button in that UIAlert. 144 145 00:11:42,580 --> 00:11:49,450 So whereas currently, we're creating this new category which was initialized using a context because 145 146 00:11:49,450 --> 00:11:54,010 we were using Category as a NSManagedObject. 146 147 00:11:54,010 --> 00:12:01,840 But now our category is just going to be a straight up object from the Category data model. 147 148 00:12:01,840 --> 00:12:07,870 And the new category also has a property code name because we defined it over here, and that's going 148 149 00:12:07,870 --> 00:12:12,610 to be set to equal the text that's currently inside the textField of the UIAlert. 149 150 00:12:12,610 --> 00:12:18,640 And finally, all we have to do is change this saveCategories method, because at the moment, it tries to 150 151 00:12:18,640 --> 00:12:28,690 save the context. Whereas what we need to do is to try to write to our Realm, so try realm.write 151 152 00:12:28,750 --> 00:12:37,300 and we're going to try to say realm.add category, and that is going to be the new category, 152 153 00:12:37,300 --> 00:12:37,540 right? 153 154 00:12:37,600 --> 00:12:41,050 So that will need to be passed in to this method. 154 155 00:12:41,050 --> 00:12:48,610 So let's replace this method to be called save and it's going to take something called a Category, and 155 156 00:12:48,610 --> 00:12:54,370 that is going to be of type Category, and that will then get passed in here, 156 157 00:12:54,370 --> 00:13:02,110 and we now have to fix the part where we call that method. And we're going to say save category is going 157 158 00:13:02,110 --> 00:13:06,580 to be the newCategory that we just created over here. 158 159 00:13:06,580 --> 00:13:12,220 So, now if we hit command B to refresh and try to get rid of some of the errors that don't actually belong 159 160 00:13:12,220 --> 00:13:15,530 here, then our IBAction is looking pretty clean. 160 161 00:13:15,640 --> 00:13:22,690 Now, we've still got some other errors in this code and also in our TodoListViewController. But I'm 161 162 00:13:22,690 --> 00:13:29,470 going to simply comment out all of this and I'm gonna go into the TodoListViewController and find 162 163 00:13:29,950 --> 00:13:38,740 those errors, and we're also going to comment that out, and I'm going to comment out this particular function, 163 164 00:13:39,040 --> 00:13:41,910 as well as this entire extension. 164 165 00:13:41,950 --> 00:13:48,640 And finally, we're going to also come on out the loaItems and I'm going to hit run to see if we can 165 166 00:13:48,970 --> 00:13:50,110 build our app. 166 167 00:13:50,200 --> 00:13:50,580 Okay. 167 168 00:13:50,590 --> 00:13:59,380 So currently, all that our code should be able to do is when we press the addButtonPressed, we should 168 169 00:13:59,380 --> 00:14:06,820 get a UIAlert, and if we type some text into the UIAlert, then it should create a new object from the 169 170 00:14:06,820 --> 00:14:15,620 class Category, and we should be able to save that category into our Realm container by using realm.write 170 171 00:14:15,670 --> 00:14:16,850 and realm.add. 171 172 00:14:16,920 --> 00:14:18,130 So let's give it a go. 172 173 00:14:18,190 --> 00:14:29,270 Let's press Add and let's create a new category called Home and add one called Work. And if we have a look 173 174 00:14:29,300 --> 00:14:35,270 inside our Realm Browser, then you can see that we've got three data models now. So Data is a little bit 174 175 00:14:35,270 --> 00:14:42,290 of a relic back from when we created it in our App Delegate. An item is empty because we've yet to implement 175 176 00:14:42,290 --> 00:14:44,630 any code inside the TodoListViewController. 176 177 00:14:45,320 --> 00:14:54,680 But our Category model has two new objects, one with the name Home, one with the name Work, and they have 177 178 00:14:54,680 --> 00:14:58,140 an associated list of items. 178 179 00:14:58,160 --> 00:15:06,320 Now, the list currently is zero, but as soon as we start assigning some items to that list, then these will 179 180 00:15:06,320 --> 00:15:08,780 be populated as we'll see a little bit later on. 180 181 00:15:08,840 --> 00:15:15,680 But what we can confirm is that our code worked and we were able to save and persist our categories. 181 182 00:15:15,710 --> 00:15:24,980 So now all that's left to do is to load our data, not from our context or Core Data, but from our realm. 182 183 00:15:24,980 --> 00:15:28,850 So for all of that and more, I'll see you on the next lesson.