0
1
00:00:00,300 --> 00:00:05,730
So, now that we've had to look at what's the code inside our AppDelegate, this is a good time to go back
1

2
00:00:05,730 --> 00:00:11,250
into our TodoListvView Controller and fix all of these errors that we've got by switching over from a
2

3
00:00:11,250 --> 00:00:16,700
custom class that saved using plist to our Core Data data model.
3

4
00:00:16,830 --> 00:00:22,340
And in the process, we'll learn about how to create or rather save data using Core Data.
4

5
00:00:22,350 --> 00:00:28,500
So the first thing that we need to change is that instead of creating a newItem as a new object of
5

6
00:00:28,500 --> 00:00:33,710
item, we actually need to initialize our Core Data object a little bit differently.
6

7
00:00:33,780 --> 00:00:40,790
So if we say let newItem = item, which if you remember is our Core Data class,
7

8
00:00:40,860 --> 00:00:46,740
so if you hold down option and click on it, you can see it's an i object of the type 
8

9
00:00:46,740 --> 00:00:47,550
NSManagedObject.
9

10
00:00:47,850 --> 00:00:55,830
And if we open a round bracket to initialize it, then we get to specify the context where this item is
10

11
00:00:55,830 --> 00:00:56,960
going to exist.
11

12
00:00:56,970 --> 00:00:58,380
So what is that context?
12

13
00:00:58,380 --> 00:01:03,550
Well, it's basically going to be the viewContext of our persistentContainer.
13

14
00:01:03,660 --> 00:01:09,510
So while we're inside the same class, it's easy to access this variable called persistentContainer.
14

15
00:01:09,690 --> 00:01:13,510
But if we're inside TodoListViewController, how do we create that context?
15

16
00:01:13,530 --> 00:01:26,550
We can just say let context = AppDelegate.persistentContainer.viewContext. And the
16

17
00:01:26,550 --> 00:01:30,240
reason why this doesn't work is because AppDelegate is a class,
17

18
00:01:30,300 --> 00:01:33,210
it's not the object of AppDelegate.
18

19
00:01:33,210 --> 00:01:39,050
So remember, when we refer to the TodoListViewController, for example, we won't try to call its
19

20
00:01:39,060 --> 00:01:42,670
methods or grab its properties by calling the class.
20

21
00:01:42,720 --> 00:01:46,300
Instead, we need to get the object of AppDelegate.
21

22
00:01:46,350 --> 00:01:51,420
So this would be the blueprint and we need to get the object that's created from the blueprint.
22

23
00:01:51,420 --> 00:01:59,580
So this, again, is where our handy singletons come into use. And instead of calling App Delegate, I'm instead
23

24
00:01:59,580 --> 00:02:04,190
going to tap into UIApplication.shared,
24

25
00:02:04,440 --> 00:02:07,030
and this is a singleton app instance.
25

26
00:02:07,050 --> 00:02:13,410
And at the time point when our app is running live inside the user's iPhone, then the shared UIApplication
26

27
00:02:13,470 --> 00:02:16,870
will correspond to our live application object.
27

28
00:02:16,900 --> 00:02:25,410
And inside this shared UIApplication object is something called delegate, and this is the delegate of
28

29
00:02:25,410 --> 00:02:26,610
the app object,
29

30
00:02:26,760 --> 00:02:29,190
alternatively known as the AppDelegate,
30

31
00:02:29,190 --> 00:02:33,600
and we're going to downcast it as our class AppDelegate.
31

32
00:02:33,600 --> 00:02:38,480
So let's just give you a bit more space to see that whole line as it is.
32

33
00:02:38,640 --> 00:02:41,790
So we're tapping into the UIApplication class.
33

34
00:02:41,790 --> 00:02:47,970
We're getting the shared singleton object which corresponds to the current app as an object, tapping
34

35
00:02:47,970 --> 00:02:53,410
into its delegate which has the data type of an optional UIApplicationDelegate.
35

36
00:02:53,430 --> 00:02:58,970
We're casting it into our class AppDelegate, because they both inherit from the same superclass
36

37
00:02:58,980 --> 00:03:00,350
UIApplicationDelegate.
37

38
00:03:00,390 --> 00:03:07,950
This is perfectly valid and we now have access to our AppDelegate as an object.
38

39
00:03:07,950 --> 00:03:13,650
So we're able to tap into its property code persistentContainer and we're going to grab the viewContext
39

40
00:03:14,160 --> 00:03:19,830
of that persistentContainer. So we can now say our context is this context.
40

41
00:03:19,830 --> 00:03:27,810
Now, the next error that we have is inside saveItems. And because we're no longer using the encoder,
41

42
00:03:27,810 --> 00:03:28,870
we can delete that,
42

43
00:03:29,220 --> 00:03:32,700
and we have to delete all of this as well.
43

44
00:03:32,730 --> 00:03:40,620
So what we ultimately need to do inside our saveItems method is we need to be able to commit our context
44

45
00:03:40,620 --> 00:03:43,790
to permanent storage inside our persistentContainer.
45

46
00:03:44,010 --> 00:03:51,210
And in order to do that, we need to call rye context.save. And that basically transfers what's currently
46

47
00:03:51,210 --> 00:03:53,770
inside our staging area or our scratchpad
47

48
00:03:53,790 --> 00:03:57,690
that's the context to our permanent data stores.
48

49
00:03:57,720 --> 00:04:04,130
So inside the do block, we need to be able to say context.save.
49

50
00:04:04,260 --> 00:04:07,060
Now, where are we going to get our context?
50

51
00:04:07,080 --> 00:04:11,840
Well, it's going to be exactly the same as this.
51

52
00:04:11,980 --> 00:04:18,250
So we can either copy and paste it over here or whenever you're copying and pasting the exact same pieces
52

53
00:04:18,250 --> 00:04:21,220
of code, then it's a good time point to evaluate.
53

54
00:04:21,220 --> 00:04:25,240
Maybe we should make it a shared constant up here.
54

55
00:04:25,320 --> 00:04:32,730
So, now instead of having this long line of code here, we can simply say let newItem = item 
55

56
00:04:32,730 --> 00:04:37,630
the context is going to be self.context because we're inside a closure.
56

57
00:04:37,830 --> 00:04:42,960
And down here, we can simply say context.save and mark it with the "try" keyword.
57

58
00:04:43,110 --> 00:04:51,930
And inside the catch block, we're going to print and say "Error saving context" with this error message.
58

59
00:04:52,080 --> 00:05:00,210
So all that we've done so far is to set up the code to use Core Data for saving our new items that have
59

60
00:05:00,210 --> 00:05:03,150
been added using the UIAlert.
60

61
00:05:03,150 --> 00:05:09,330
So I'm going to comment out the load items function and I'm also going to comment out the part where
61

62
00:05:09,330 --> 00:05:14,930
we call that function. And if we want to be able to use item which, if you remember, is an NSManagedObject,
62

63
00:05:14,970 --> 00:05:18,320
so it's something that only exists in the Core Data framework.
63

64
00:05:18,360 --> 00:05:21,590
Then, of course, we also need to import Core Data,
64

65
00:05:21,810 --> 00:05:24,540
and now those errors will go away.
65

66
00:05:24,540 --> 00:05:28,600
So if I run the app now, you're going to see that we're going to come into an interesting bug.
66

67
00:05:28,650 --> 00:05:31,470
So when I hit Add, let's create a new item.
67

68
00:05:35,030 --> 00:05:41,060
And once I hit an add item, you can see it show up inside the table view, but that's only because it's being
68

69
00:05:41,120 --> 00:05:42,820
added to an array.
69

70
00:05:43,010 --> 00:05:51,170
And if we drag up our debug console, we'll see the reason. And it gives us an error with a code, and it says,
70

71
00:05:51,350 --> 00:05:53,030
"Error saving context."
71

72
00:05:53,120 --> 00:06:00,080
So that, of course, refers to this line here. And this is the error that we're catching because we wrote
72

73
00:06:00,080 --> 00:06:02,020
this "Error saving context," remember?
73

74
00:06:02,270 --> 00:06:10,220
And the error message is "The operation couldn't be completed" because if we have a look at our data, we've
74

75
00:06:10,220 --> 00:06:13,250
got this item called done and it's equal to nil.
75

76
00:06:13,250 --> 00:06:16,910
So because our item done is not optional,
76

77
00:06:16,910 --> 00:06:21,830
we have to provide it with a value when we create our newItem.
77

78
00:06:21,860 --> 00:06:29,690
So over here, in addition to adding a title, we're going to set the done to false for every single new
78

79
00:06:29,690 --> 00:06:32,110
item that we add into our table view
79

80
00:06:32,150 --> 00:06:35,630
which makes sense, right? Because everything starts off being not done.
80

81
00:06:35,900 --> 00:06:39,220
So let's run our app again and see if this now works.
81

82
00:06:39,230 --> 00:06:44,850
So let's add a new item.
82

83
00:06:45,030 --> 00:06:52,200
And now you can see that the item has been added to the table view and we don't get any errors in our
83

84
00:06:52,200 --> 00:06:54,580
debug console from that catch block.
84

85
00:06:54,850 --> 00:07:01,830
So the problem, though, is that right now, we haven't yet got code that loads our items from our Core Data
85

86
00:07:01,840 --> 00:07:02,640
data model.
86

87
00:07:02,830 --> 00:07:10,150
And if I terminate this app and I reopen it, you can see that we have no items in here. But we did save
87

88
00:07:10,150 --> 00:07:13,770
our data using Core Data and we didn't get any errors,
88

89
00:07:13,780 --> 00:07:15,330
so it succeeded.
89

90
00:07:15,640 --> 00:07:17,160
So how can I prove this to you?
90

91
00:07:17,260 --> 00:07:23,620
Well, in the next lesson, I'm going to show you how you can view your SQLite database and see the
91

92
00:07:23,620 --> 00:07:25,720
items that get saved into it.
92

93
00:07:26,140 --> 00:07:28,890
So for all of that and more, see you on the next lesson.
