[MUSIC]                         
Stanford University.            
>> All right, well,             
welcome to Stanford CS193P.     
This is Developing iOS          
Application, Winter of 2017.    
And the only topic for          
today is a big one, Core Data,  
which is an object              
oriented database.              
But before I dive into this,    
I'm actually going to revisit   
that demo we did last time      
just briefly, because we        
ran out of time and so          
I wasn't able to show           
you the refresh control.        
Now I posted the code for       
it, so                          
I'm not gonna type              
all the code in here.           
But I'm just gonna              
briefly show you                
how that refresh                
control worked, okay?           
Okay, so we missed that.        
So here is the app we           
had from last time.             
By the way,                     
I have modified our app         
here to change our              
request a little bit.           
If you remember this line       
of code from last time,         
it used to just                 
have the query.                 
But I've changed it to also     
filter out retweets and         
I've also put on the safe       
filter, which hopefully will    
make it so                      
that when I do these look ups,  
these sort of up looks, we      
don't get stuff on the screen,  
you know this is                
a family show,                  
so we don't want to see         
some of that stuff.             
Anyway, hopefully,              
that'll work.                   
So let's go back here and       
take a look at what             
this looks like.                
There's my simulator            
right here.                     
So let's go ahead and search.   
Let's try Trump again and       
cross our fingers, all right.   
So that's not, I don't see      
anything too terrible there.    
Okay so what we added was this  
UI where we can pull down.      
Okay and it adds more tweets,   
you see how it added            
a tweet there?                  
We have the second              
pull right there,               
this was with the first pull.   
And we pull down again,         
no tweets this time, okay?      
So each time we pull down       
it's doing another twitter      
fetch, and                      
may get more tweets depending   
if people are tweeting or not.  
So let's take a look at         
the code to do this, again,     
I posted this code, but         
we'll just look at it,          
I'm not gonna type it all in,   
we're just gonna look           
at it real quick.               
First of all, let's talk about  
how do I get this UI where      
we pull down and it calls       
a method, or whatever?          
So let's go to look             
in our storyboard.              
All right, so                   
here's our storyboard, and      
what I did was I just selected  
my table view controller and    
I went down here to             
this refreshing.                
You see that                    
refreshing choice?              
And I changed it from disabled  
to enabled, and when I set it   
to enabled nothing              
changed here in the UI.         
You can't see any               
spinning thing, but             
over here in the document       
outline it created this         
refresh control right here.     
And so I can control drag from  
the document outline just as I  
can through here.               
So all I did to make this       
work is I just brought up       
my controller right here.       
And here's the method I         
did it with right here.         
I just Ctrl dragged from the    
Refresh Control to this method  
called refresh, okay?           
That's all I did to,            
to make that happen.            
And inside refresh,             
I just called that same method  
I had before, searchForTweets.  
This one right here, the one    
that search for tweets.         
And that used to                
look like this,                 
I only changed one              
thing in here.                  
It used to just get             
the twitterRequest by           
looking at our                  
search term up here.            
Remember this function?         
And all I did was added this,   
which says, if                  
the lastTwitterRequest has a    
newer version, then use that.   
But if it doesn't, then         
default back to doing to query  
request the way we used to.     
The only other things that I    
had to do was turn the refresh  
control off, you do that        
with the end refreshing.        
So I just did that when I went  
back to the main queue here,    
to get my results,              
so I turned it off.             
I also turned it off if for     
some reason I couldn't get      
any request or whatsoever.      
Okay, there's nothing in        
the search term field and       
I couldn't get a newer          
version of my last request.     
So I just said, I'm gonna       
make sure that thing is not     
spinning and spinning forever.  
They wanna get out              
of here with that.              
And the only other thing        
I had to do was up here,        
when the search text changes,   
someone types#Stanford or       
something like that, I need to  
invalidate that last Twitter    
request so that it's not        
trying to get new versions      
of the previous                 
one that I had.                 
I want it to do the new one.    
And the way that I made it so   
that we had these little        
titles right here, see these    
titles two, three, four, five?  
I implemented another UI table  
view data source method,        
this one down here.             
Called                          
titleForHeaderInSection.        
I just put titles               
on the sections.                
Remember, each section is       
another pull from Twitter.      
And so I just have each title.  
It's actually gonna be the      
count of things I had minus     
the section number.             
So the top one                  
is section zero.                
So section zero is gonna show   
the number of pulls             
that I've made.                 
tweets.count is how             
many pulls I made.              
And it's obviously gonna        
decrement as                    
the sections go down.           
Okay, so                        
that's what gave us this.       
And you can see that            
the longer we wait,             
obviously it pulls              
more information,               
as tweets pile up.              
Okay, let's go back             
to our slides.                  
All right, here we go.          
So Core Data is this big        
framework inside of iOS for     
doing object-oriented           
databases.                      
So let's talk a little bit      
about what that means.          
So, when do you                 
need a database?                
Well you need a database when   
you have a large amount of      
data, and especially if you     
want to kind of make queries    
into that data and find out     
things about that data and      
the relationships between       
all the things in there.        
You really can't                
do that by like,                
taking a big dictionary or      
a big array and                 
searching through it,           
you need a database.            
And so there's a lot of         
technologies for databases out  
there but most of them          
are not object-oriented.        
So we have this framework       
that Apple provides called      
Core Data, it's what we call    
an object-oriented database     
but actually, it's really not   
an object-oriented database     
on the inside.                  
It's only an object-oriented    
database on the outside.        
The side that you look at.      
Underneath, it's actually       
a relational database usually.  
Now Core Data is designed to    
have any backend of storage.    
But it's primary                
implementation is on top of     
SQL which is                    
a relational database.          
How many people know            
what SQL Database is?           
Okay, almost all of you, good.  
So, if we had to do databases   
in our iOS apps using SQL,      
we'd be like no, I have         
to learn this whole query       
language, and                   
how am I gonna do this?         
Not to worry, we don't have to  
know any SQL to use core Data.  
No SQL whatsoever- we're        
just gonna purely do this       
on the object side.             
So how does this work?          
How does core Data work?        
Well, first we're gonna         
create a visual mapping         
between things in               
our database and                
some objects that we're gonna   
be able to program with         
in our object-oriented          
code that we like.              
And kinda roughly, it's         
the tables in the database      
are kinda gonna be objects.     
And the columns in              
the tables are kind of vars.    
But we don't even really        
care what it's doing there.     
What we're gonna focus          
on is this visual map,          
this visual description         
basically of our schema.        
Okay, how many people know      
what the word schema means?     
Okay, so two-thirds of you.     
So schema is basically          
the description of what's       
in your database, not the       
contents of it but how all its  
data types are and how they     
relate to each other, etc.      
So we're gonna do all           
that graphically.               
And this is what                
it looks like.                  
First, if I wanna use           
Core Data in my app,            
I'm almost certainly going      
to wanna click this button      
that says Use Core Data.        
We've seen it every time we've  
created an app, and we haven't  
clicked it so far, but          
now we are going to click it.   
And clicking                    
Use Core Data there,            
is gonna create two things for  
us, this visual map,            
and some code in                
your App Delegate.              
And I'm gonna talk about        
both of those things.           
Now before I go to              
the next slide,                 
notice that the name of this    
app is CoreDataExample.         
That's the, just the name of    
the app that I typed in there.  
So when I create this app,      
clicking that                   
Use Core Data on, you'll see    
that it created this file,      
CoreDataExample.xcdatamodeld.   
So it chose the name            
of my app as it.                
And this is going to be         
our data model, all right?      
And so we'll, we'll talk        
about the AppDelegate           
code that Use Core Data also    
generated a little bit later.   
Right now we're gonna focus     
on this data model file.        
All right, but before we even   
do that, what happens if we     
have an existing app and you    
did not click Use Core Data?    
And now you decided, hey,       
I wanna add core data.          
Like maybe Smashtag Assignment  
5 comes out and                 
I tell you to add some          
Core Data to Smashtag.          
And you're like, woh,           
I can't go back and             
click Use Core Data,            
it's too late.                  
So you're gonna have to         
create this data model file     
using new file.                 
So you just go to File          
> New > File like this.         
You're not gonna pick any of    
the things we've picked so      
far.                            
You're gonna scroll down        
to the section that             
says Core Data.                 
And inside there these,         
there's two things,             
Data Model and Mapping Model.   
And make sure you pick Data     
Model because that's what you   
want to do here is              
create your data model,         
your schema essentially,        
for your database.              
It's gonna ask you              
what you wanna call it.         
Now, you don't have to call     
this the same as the name of    
your application like           
Use Core Data button does.      
You can call it                 
anything you want.              
So here, just to be different,  
I've called it Model,           
it's my model.                  
And by the way,                 
your core data is usually       
the model of a lot of MVCs.     
Okay, a lot of MVCs, their      
job is going to be to display   
the data in the database, and   
so this data model is actually  
the MVC model as well for       
a lot of MVCs.                  
So I'll call this one model,    
and                             
you can see it created          
model.xedatamodeld.             
So whether you get that file    
by doing Use Core Data or       
whether you get it by           
creating it yourself,           
you're gonna have               
this mapping file.              
Now, let me go back to          
that AppDelegate thing.         
I said they was gonna put some  
code in your AppDelegate.       
It's very small                 
amount of code.                 
But I wanted to show            
it to you right here.           
This is what it looks like.     
It just creates this            
one var right here.             
By the way, if you didn't do    
Use Core Data, of course,       
you need this code              
in your AppDelegate,            
how are you gonna get it?       
Just go create some             
dummy application.              
Call it Foo, it doesn't really  
matter what you call it.        
Click Use Core Data             
when you create it and          
then copy this code from        
that AppDelegate to here.       
Okay, the code is               
identical from every app.       
The only difference between     
any of those things is this     
one string right here.          
You see that string?            
That's the name of              
that xcmodeld file, so          
datamodeld file.                
So with our core data example,  
this string would               
be CoreDataExample.             
When we went back and created   
it on our own with new file,    
of course, we called it Model.  
So just make sure this string   
matches the name of the file,   
the xcmodel datamodeld file,    
okay?                           
So that's what you need to      
do if you didn't do the use     
Code Data originally            
you are going back and          
adding it- just copy and        
paste.                          
It's only this one var really,  
it does provide another thing   
in your AppDelegate which is    
a function called saveContext.  
It's a very simple              
little function.                
I'm gonna show you how you      
could write it yourself.        
If you wanna copy it in,        
you can.                        
Also I notice that they have    
applicationWillTerminate which  
is this application,            
AppDelegate method,             
that gets called right          
before you get terminated or    
you terminate it in any way     
and they call saveContext.      
Well, it's a kind of an idea,   
a good idea.                    
saveContext() just              
saves your database.            
That's what saveContext does,   
all right?                      
So this is how you can make     
up if you didn't do it.         
So anyway, you can see that     
the only thing in here          
is this lazy var                
persistentContainer, and        
I'm gonna talk all about        
persistentContainer,            
because that's the thing        
that essentially contains       
your database, all right?       
But let's go back and           
talk about the visual map.      
Cuz we have to have a visual    
map before we can do anything   
in our database because we      
have to have some things in     
our database, some objects and  
things like that.               
And Core database stores        
things in this kind of very     
straightforward way.            
It looks very object-oriented   
in our code because             
in Core Data terms              
it's storing entities,          
which look like                 
classes to our code.            
Attributes, which look          
like vars on our classes.       
And relationship, which just    
look like vars that point to    
other objects in the database,  
other entities, etc.            
And so we're gonna use this     
what I'm calling a storyboard.  
It's not, don't get confused,   
this is not a storyboard,       
okay?                           
You know what a storyboard is,  
your Interface Builder thing.   
But it's kind of                
like a storyboard,              
that's why it's in quotes for   
databases.                      
It's a graphical,               
visual editor to create and     
describe all these entities,    
attributes and relationships,   
okay, that's what               
we're gonna do here.            
So let's start by               
adding an entity.               
Very easy, we go down to this   
button on the bottom here       
called Add Entity.              
Okay, to add an entity.         
By the way, there's couple      
other things in that if you     
hold down on that button        
you'll see Add Fetch Request,   
and Add Configuration.          
I don't have time to talk       
about those unfortunately,      
but especially Add Fetch        
Request is kind of a cool one.  
So, if you can take what I      
teach you here and extend it    
by going and learning about     
that, that would be great.      
So you click Add Entity,        
it creates a new                
entity called Entity.           
Cuz it doesn't know what        
name you want for it yet.       
And like I say,                 
this analogous to a class.      
Now in our code we're gonna     
see any instances of this       
entity as instances of a class  
called NSManagedObject.         
So NSManagedObject super        
important in Core Data.         
It is the super class or        
the class of everything that    
comes, all these entities that  
come out of the database.       
It's like the thing that        
represents them in our code,    
and we'll see all about that.   
So for my kind of slides here,  
what I'm gonna do is create     
a database that would have      
stuff like we got               
from Twitter.                   
So it's gonna have tweets and   
we're gonna have                
Twitter users.                  
So those are gonna be two       
entities that we have and       
you're gonna see eventually,    
we're gonna have Tweet and      
TwitterUser classes             
in our code and                 
we're gonna access vars and     
all that stuff.                 
So I'm gonna rename             
this entity,                    
this, that I added that         
was defaulted to entity,        
I'm gonna rename it and         
call it Tweet.                  
So this is gonna be the first   
entity that I'm creating        
in the database.                
Now, an entity can              
have attributes.                
Those are kind of like vars,    
and relationships.              
Those are like vars that        
point to other entities.        
And I told you this fetched     
properties down at the bottom,  
I'm not gonna talk about.       
Very cool, but                  
not gonna talk about them.      
Not just time-wise.             
So let's go and add some        
attributes to this entity.      
Real easy,                      
you click this plus button,     
there's also                    
an Add Attribute button,        
see it down in the lower        
right hand corner there.        
But I'm gonna click             
this little plus                
button right there under        
the section called Attributes.  
And when I do there it adds a   
new attribute called attribute  
and I'm gonna edit              
its name directly,              
just like I did                 
the entity name.                
I'm gonna change                
this to be text.                
So, this is gonna be our tweet  
text, the 140 characters        
of the tweet is gonna be        
this particular attribute.      
Now, notice as soon as I        
did that, I got an error.       
In the corner there,            
this red error.                 
And the reason for              
that is all attributes          
have to have a type.            
They can't just be undefined    
type like this one is.          
You see where it says           
the type is undefined.          
So, we need to change           
that to be a type.              
And it's really easy, right     
there where it says undefined.  
We're just going                
to mouse down,                  
it's gonna bring up a menu and  
we can choose our type.         
Now, these are the types        
we have to choose from.         
A lot of different numeric      
types like 16-bit integers,     
32-bit integer, etc.            
Doubles, floats,                
can a be string of course,      
a Boolean value, a date which   
is going to look like a date,   
you know,                       
the date struct in our code.    
And binary data which is gonna  
look like the data struct       
inside our code.                
So, these are gonna map to      
very familiar data types        
that we see.                    
There is that one at            
the bottom there,               
transformable, another thing    
I'm not gonna talk about.       
But transformable allows        
you to store anything           
into the database by            
converting it to a data, and    
then converting it              
back on the way out.            
And so if you pick              
transformable there,            
you're gonna have to            
do some extra work.             
To tell Core Data about that    
transformation, and that's why  
I don't really have time to     
tell you about, but just know   
that if you wanted to store     
something like a CGRect.        
Actually, if I was going to     
store a CGRect, I might use     
the function, there's some      
function called something like  
NSStringFromCGRect.             
It gives you a string, and      
then there's                    
NSCGRectFromString or           
something like that.            
So I'd probably store           
it as a string,                 
but if I had something more     
complicated than that,          
then I might use                
a transformable.                
All right, these attributes     
here are going to be accessed,  
we're gonna get and             
set their values.               
Well actually, we're not going  
to do this but fundamentally    
the way you do it is you        
have these two methods,         
value(forKey) and               
setValue (forKey).              
And I'll talk about how         
we're gonna use that, but       
that's how we're gonna set and  
get the values on an entity.    
Notice the error went           
away as soon as we              
gave this thing, a type.        
So here I'm gonna add some      
more attributes, identifier,    
which is just some string       
that identifies the tweet and   
then created,                   
which was when it was tweeted.  
Notice I'm setting created's    
type here to be date because    
it is a date, obviously,        
when the thing was created.     
Now this is one way to look at  
our entities and attributes,    
this kind of table form.        
But we can actually look at     
it in graphical form as well.   
If you see down in the corner   
where it says editor style.     
If I click on                   
the other button there,         
the one that looks a little     
more like a graph,              
then it shows me                
the same thing but              
in this graphical form.         
It's even on graph paper,       
all right?                      
And in this form                
right here we can do            
all the things that we          
did in the other one.           
For example,                    
I can still add entity here.    
So I'm gonna add another        
entity for my Twitter User,     
this is people who tweet.       
And there it is,                
it called it entity again,      
that's the default.             
We'll set its name              
to be TwitterUser.              
All right, so we now have two   
entities, you see on there.     
What's kinda cool is as you     
drag these entities around,     
this, this kind of editor,      
this graphical                  
editor, will automatically      
kind of keep them spaced apart  
from each other.                
Which is kind of fun,           
especially since they're going  
to start having wires           
connecting them because         
they're going to start          
having relationships            
to each other as you're         
going to see in a moment.       
We can add attributes in this   
graphical style as well- you    
can edit those right in there   
just by double clicking on      
them, change                    
whatever you want.              
So, here I got a screenName,    
now of course I got an error    
again because I didn't set      
the type of that screenName.    
So, in this view you set        
the types by bringing up        
the inspector.                  
So you just bring up            
your normal inspector,          
attribute inspector.            
And the, here you can see       
it's inspecting screenName,     
it's got the name there.        
There's some other things       
in here like transient,         
indexed, optional.              
By the way, that optional       
doesn't mean this is optional   
like the Swift thing optional.  
This is optional like in        
SQL database terms, right.      
In relational                   
database optional.              
So I'm not gonna talk           
about any of the database       
You rarely need to set any of   
these properties right here.    
stuff of it.                    
But you do need                 
to set the type.                
So we're not gonna              
talk about that, but            
we have to set                  
the type right here.            
And the screenName,             
of course, is a string.         
So I'm just gonna               
change it to a string.          
I'm adding another attribute    
to the TwitterUser,             
this one is the name,           
the person's actual name,       
not their @ sign handle,        
but their actual name.          
Now we've built a couple        
of entities with a bunch of     
attributes on them, okay,       
and this is gonna look like     
classes with vars in            
our code eventually.            
But what about relationships,   
obviously a Tweet and           
a TwitterUser have              
a relationship to each other.   
And to create relationships     
between things we just          
Ctrl+drag, this is our          
favorite gesture in Xcode and   
we're using it again.           
Ctrl+drag to create             
a relationship                  
between two things.             
And it actually doesn't matter  
which direction you Ctrl+drag,  
because you're creating         
kind of a bidirectional         
relationship.                   
So here, I did Ctrl+drag, and   
it automatically created this   
relationship, which it called   
newRelationship on both sides.  
And this relationship is        
essentially just gonna be       
a var in our class.             
But the var's type is either    
going to be the type, if it's   
like a Tweet, you know,         
it's gonna be a single one, or  
it could be an NSSet,           
if it's many of them.           
Like a Twitter user might       
have many tweets, and           
I'll talk about                 
that in a moment.               
So, from a Tweet's perspective  
this relationship to            
a TwitterUser is the Tweeter.   
The person who                  
tweeted this tweet.             
So, I'm going to change the     
name of this relationship on    
the Tweet side to be tweeter    
instead of newRelationship,     
which was the default.          
But, on the other, okay, so     
that's why I call it tweeter.   
On the other side               
the TwitterUser from its        
perspective though, okay, the   
relationship of the tweet is    
the tweets that this            
Twitter user has tweeted.       
Okay, it's not tweeter, the     
Twitter user is the tweeter,    
so he would never call          
this relationship tweeter.      
He's gonna call this            
relationship tweets             
because this is the tweet.      
Now notice that's plural,       
okay,                           
we'll talk about                
that in a second.               
Notice that when we do this,    
Xcode tracks if I'm inspecting  
the tweet's relationship there  
on the TwitterUser side,        
it knows the inverse.           
It knows that tweeter goes      
the opposite direction,         
there's always gonna be         
an inverse relationship.        
So let's talk about that        
tweets being a plural right?    
So a tweet can only             
have one tweeter.               
Only one person can             
have tweeted it, but            
a Twitter user can tweet        
thousands of tweets, okay?      
And so                          
that's a little different       
kind of relationship.           
So how do we specify that?      
We call the tweets              
relationship the,               
a to many relationship          
because obviously the Twitter   
user can have many tweets.      
So that's called to many        
in database parlance, and       
you set that right              
in the Inspector.               
So you just click               
on that tweets and              
you go over here to             
where it says Type,             
and instead of having it be     
To One you're gonna change it   
to be To Many, okay, so now     
it's a to many relationship.    
Right there, you can see that   
it's changed a little bit as,   
and we'll show                  
that in a second.               
But the type of this            
relationship now on the tweet   
side is still type              
NSManagedObject,                
because it points to another    
entity in the database.         
And we know that                
the objects in the database     
are represented by              
an NSManagedObject.             
So that's gonna be              
the type of that var.           
Although we're eventually       
gonna make it even better than  
that, but                       
on the other side though,       
the type of that var is NSSet   
of NSManagedObject, okay?       
Now NSSet, there is             
a Swift struct called set.      
It's a generic type, it's just  
like an array where you have    
to say what's in an array,      
same thing with a set you       
have to say what's in it.       
NSSet is kind of an older       
Objective-C kind of set.        
It's not generic,               
it's untyped.                   
The things in NSSet are any,    
which we kinda need a little    
bit here cuz we really don't    
know what kinds of things       
are in there.                   
However, in your code you       
can cast from this NSSet        
of NSManagedObject to a set of  
what you know to be in there    
using as question mark, and     
if that in fact is what's       
in there, it will work.         
So that's the NSSet there.      
One last thing I'm gonna        
show you here before            
we get back to the slides       
is this Delete Rule.            
You see the delete              
rule on the,                    
clicked on tweets on here so    
we're inspecting tweets.        
And this delete rule            
tells you what happens          
to the pointed-to tweets if     
we deleted this Twitter user.   
Cuz if I delete                 
this Twitter user,              
does that mean I delete all     
of the Twitter user's tweets?   
Well, it depends on this        
delete rule right here.         
this delete rule is saying      
nullify, which would mean no.   
So right now,                   
Those tweets would stay in the  
database, and their tweeter     
will be set to nil because      
their tweeter got deleted.      
But there is a cascading        
delete rule, which would say    
if I delete this thing then     
delete everything that it       
points to, just go right        
down the graph and              
delete everything.              
So that's what controls what    
happens when you delete.        
Now I'm not gonna ask           
you to even do delete;          
I guess I might ask you an      
extra credit to do delete in    
assignment five.                
Because deletion kinda-         
you're really gonna know what   
you're doing- when you          
can delete things, and          
what kind of delete             
rules you want.                 
But I just want to let          
you know that you specify       
the delete rule right           
here in the inspector.          
Okay, now that you've defined   
all your entities, attributes   
in relationships, then what     
can we do with these things?    
Well to do anything with it     
we need to get a hold of them   
in our code,                    
grab onto them basically, and   
to do that we need              
another important class,        
NSManagedObjectContext, so      
I told you                      
all those things in the         
database are NSManagedObjects,  
you need                        
an NSManagedObjectContext,      
which represents a database     
to do anything with them,       
to get any of them,             
to create any of them, etc,     
this is the hub around which    
Core Data activity turns,       
as I say there.                 
So how do I get one of these    
NSManagedObjectContext?         
And the answer is, you need     
a persistentContainer.          
Woo-hoo, and you know           
where to get one of those.      
You just click,                 
Use Core Data, and              
it's gonna appear in            
your AppDelegate.               
You're gonna get                
that lazy var,                  
that's called                   
persistentContainer.            
And that is gonna be            
a persistentContainer.          
And from that you               
can get the context.            
Now, if you have the lazy       
var in your AppDelegate,        
How the heck do                 
you call that var?              
How do you get that var?        
And this is how you do it,      
okay?                           
You get a copy of the shared    
UIApplication, now,             
we didn't talk about this but   
your app has this one and       
only UIApplication object that  
represents your application     
and you get it by doing         
UIApplication.shared,           
it's a var.                     
Static var in                   
UIApplication class.            
Gives you the shared one.       
Then you're gonna access this   
var in UIApplication which is   
its delegate.                   
Now, its delegate is            
automatically set up for        
you to be this Swift class      
AppDelegate that you see        
always; we always put it        
off in Supporting Files and     
get it out of our way,          
but it's created for you,       
it's a nice little class.       
We're going to talk about the   
application life cycle, and     
where it fits in, in a little   
bit, but for now all            
you need to know is you can     
get AppDelegate, and you want   
to send persistentContainer     
to it to get that var, but of   
course you have to as it to be  
the AppDelegate class first.    
So this is the code             
you're going to use.            
(UIApplication.shared.delegate  
as!                             
AppDelegate) All that           
in one expression               
dot persistentContainer         
now you're gonna get this       
persistentContainer, and        
notice I'm doing as             
exclamation point this will     
crash if my App Delegate is     
not in fact App Delegate,       
but it's already wired up       
to be that for you when         
you create a new project,       
so that should                  
never be a problem.             
Okay?                           
So                              
now I have this                 
persistentContainer,            
I need to get                   
the context out of it.          
And, so,                        
the container has an awesome    
var called viewContext.         
And the viewContext is an       
NSManagedObjectContext that's   
only suitable for               
use on the main queue.          
This is in red,                 
you know whenever you see       
anything in red on my slides,   
this means pay attention,       
it will matter for              
your homework,                  
and in life, but                
you can only use this           
viewContext in the main queue,  
it called viewContext because   
you use it with your views,     
okay, your UI views, that's     
why we call it viewContext.     
So why do I make a point        
about this main queue?          
Well, the reason I do that is   
because NSManagedObjectContext  
is not thread-safe.             
But I'm gonna talk you, talk    
to you about how we can do      
multithreaded database stuff    
towards the end of this talk.   
All right, so now you have      
this viewContext then you can   
use it to do things.            
Now, it's so                    
{UIApplication.shared.delegate  
as!                             
Appdelegate).persistentContai-  
ner,                            
that's kind of                  
a messy line of code.           
There's a lot of, there's as    
and all these things in there.  
So at times we'll just          
create a static version of      
persistentContainer in          
our AppDelegate.                
Okay, we'll just call           
it the same thing.              
persistentContainer but         
it's static and                 
it's just gonna return          
that messy line of code.        
So now we can get that          
persistentContainer with        
AppDelegate.persistentContai-   
ner.                            
See what I did there?           
I just made it easier to get    
up by making that be a static,  
a class var, and we can do the  
same thing with viewContext,    
you might create a static       
called viewContext and for      
the rest of these slides you    
can assume I've done this.      
Which is good because typing    
that long messy thing would     
make all my slides              
spill over the edge.            
So I'm gonna use this           
shorter version as well.        
And you're welcome              
to create the static            
version in your                 
AppDelegate if you want         
to make your code               
a little cleaner.               
Now this viewContext in         
the persistentContainer         
There's one of them that        
represents your entire          
are shared.                     
database.                       
So it's perfectly fine to       
create a single static          
that does this.                 
By the way, what if you         
wanted multiple databases?      
You could even have             
multiple databases with         
different schema.               
Very easy,                      
if you go look at the code for  
persistentContainer in          
AppDelegate,                    
you'll see it's only            
like four lines of code.        
And you could just copy         
it to create a different        
persistentContainer using       
a different xcmodeld file.      
Instead of using model          
according to the example,       
create another one with         
a different one and             
you can just go file, new file  
and create another data model.  
You could even create two       
persistent containers with      
the same model.                 
So they would be                
separate databases, but         
have the same model,            
the same entities to that and   
the same relationship to that.  
It's perfectly                  
allowed as well.                
But for everything you're       
going to do in this class, and  
for really with most apps,      
you're going to have            
one big database.               
And you're going to have this   
one persistent container that   
is the container for it.        
All right.                      
So now I have a context in      
my hand, this viewContext.      
And what can I do?              
Well, of course, I can insert   
objects into the database.      
I can delete objects            
from the database.              
And I can query for             
objects in the database.        
So, let's talk about            
all those things.               
Let's start with insert         
because until we insert some    
data in the database we can't   
do any of those other things.   
And the way you insert          
an object in the database, or   
a way to do it,                 
and actually for                
the next few slide I'm going    
to kind of show you the,        
the essentials.                 
But, we're eventually going to  
move up to a high level and     
access this stuff in            
a much nicer way.               
But I'll tell you               
the basics of it first.         
So the basic way to put         
something in the database is    
with this really                
interesting method.             
NSEntityDescription.insertNew-  
Object(forEntityName: into:     
context).                       
Okay, that's a mouthful, used   
to be even more of a mouthful   
before they renamed it.         
And you just specify            
the name of the entity, so      
Tweet or TwitterUser.           
And you give it a context that  
is gonna be the viewContext     
you got from the AppDelegate.   
And boom, it's gonna create     
one of these in the database.   
Now all of its                  
attributes will be nil.         
Okay, although you can          
inspect the attributes in       
the data model editor and       
specify default value.          
And so it might start out       
with the default value.         
But if it doesn't,              
then they'll start out as nil.  
Okay, so that's great.          
I can now create one.           
And now I need to set those     
vars to have some value.        
I need to set the text of the   
tweet and things like that and  
I told you I'm gonna do         
this with value for key and     
set value for key.              
So for example I wanted to      
set the let's say the text,     
I could just say tweet.         
A set value for key quote       
text, to be a string.           
And you can do dot notation     
here, with value for key path.  
That's what I'm showing         
in green right there.           
You can have, if you had        
a tweet you can actually set    
the tweet's tweeter's name,     
using this dot notation to set  
value for key path tweeter dot  
name and it would go through    
the tweeter relationship        
which is kinda fun.             
I'm kinda going fast through    
this because this is a really   
terrible API.                   
First of all it's               
got any in there so             
there's not type checking       
going on here, okay?            
You could say, set value date   
for key quote text, all right?  
And that would be perfectly     
accepted by Swift.              
Date is an Any and              
quote text is a String, but     
of course that's gonna fail     
miserably at run time, okay,    
because the text is a Atring.   
So we're not really gonna       
use this API but this is        
the underlying basic way that   
Core Data is doing this.        
Yes the key is just the name    
of the attribute, and           
the value is all the things     
we've talked about before.      
I do have the blue              
Use Scalar Type there which     
is interesting.                 
If the thing you're putting     
in the database is a flow or    
an Int32 or                     
one of these things.            
It's actually gonna be stored   
in a database as an NSNumber,   
which is a class,               
it's an object, kind of         
generic holder of numbers.      
But if you flip on the switch   
in the inspector in your data   
modeller for that attribute     
saying use a scalar type,       
then it'll make the type be     
double or int or whatever,      
instead of NSNumber, so.        
I know, you had a question?     
>> Yes, so the question is,     
does set value reject           
something where                 
the types don't match?          
And the answer is, it can't.    
It doesn't know the type,       
the types are any,              
as long as it matches any- and  
everything matches any.         
So, it can't.                   
There's no way for it to have   
enough information to reject.   
As long as it matches any,      
it'll accept that as the type.  
And then at runtime,            
it will crash.                  
If you try to set a date        
to be into a string field.      
>> So                           
when it's like [INAUDIBLE]      
save context,                   
do you have to like             
make it go through.             
Or is it.                       
>> Go and remove.               
>> [CROSSTALK]                  
>> What do you                  
mean go and remove it?          
Remove what?                    
Yeah, we'll talk                
about saving in this.           
So, the question is,            
when the app terminates         
it does save context and        
they're trying to save this,    
we'll talk all about saving in  
a minute cause that's           
an important piece of this.     
That's the keys and values,     
pretty straightforward there;   
in fact we're going to talk     
about saving right now.         
We do a nice lead in.           
All these changes that you      
make with that set value even   
insert entity description for   
entity name context whatever    
that thing is called.           
All that stuff only             
happens in memory,              
if you want that to actually    
happen permanently in           
the database you                
need to save it.                
And you do that by              
telling the context,            
like that view context thing,   
to save with the method save.   
It couldn't be simpler,         
except that it can throw.       
Save is a method that           
can throw because               
maybe there's a problem         
writing out to the database.    
And there's many problems       
that could happen writing       
out to the database.            
And you need to look            
at documentation and            
kind of figure out              
what they all are.              
But the take home message       
here is you do need to save.    
If you don't save, that         
substance is gonna be lost      
when your app exists or         
whatever.                       
So you definitely just save.    
And especially when talking     
about multithreaded Core Data.  
And one thread is working.      
That thread needs to save if    
it wants any of the other       
threads to see the work         
that it's done.                 
Okay, so you can use try        
question mark here, remember,   
which means try and             
if it fails,                    
just return nil and ignore it.  
You can do that, if you don't   
mind that it didn't save.       
And the kinda things that       
can happen, saving errors.      
You could obviously have        
file system problems,           
your disk is full or            
something like that.            
But you can also have           
inconsistencies in              
the database,                   
maybe you had conflicting       
data of two threads trying to   
save to the same database, and  
they've tried to write over     
the top of each other,          
those kind of things.           
Again, a lot of those problems  
you're not gonna have,          
unless you build                
a pretty complicated,           
multithreaded application,      
or something like that,         
but, again, you gotta check     
the documentation, I couldn't,  
it would take too long for      
me to go through all of it.     
Okay now, as I said value       
forKey and setValue forKey.     
Really ugly,                    
What we really want to do is    
be able to set these vars       
as vars, we just wanna          
have a var called text          
somewhere that we can set.      
And of course we're             
exactly going to do that.       
And the way we're going to do   
that is create a subclass of    
NSManagedObject, instead of     
having NSManagedObject in       
the database we doing           
set-value, get-value on it.     
Instead we're going to create   
a subclass of NSManageObjects   
and it's going to have vars on  
there for all the attributes,   
like text, and screen name and  
all those things.               
And Xcode will generate         
all that code for               
you behind the scenes,          
you don't have to do any        
work to make that happen.       
Quite quite simple, so let's    
look and see how we do that.    
You do that by                  
inspecting the entity.          
So here I've chosen tweet.      
Okay, not any of                
its attributes but              
tweet itself, and               
I want to make it so            
it generates this magic code,   
and how do I do that?           
Well, if you go down            
on the inspector                
a little ways you               
see it says Codegen.            
See that Codegen, that's for    
generating this code,           
this magic code.                
Now, you actually have          
a couple of choices here for    
the Codegen.                    
The default I believe is        
this one Class Definition.      
If you choose this one it will  
generate that subclass for      
you and it will just work.      
Okay, you'll be able to         
access your tweets as a class   
called tweet.                   
With all the vars.              
Now this sounds good and        
it is good; by the way if       
you do this class definition    
codegen it will not show        
up in your navigator.           
It's all behind the scenes-     
you never really see this file  
that is, this codegen           
file that generates.            
So don't look for               
it there if you put this        
on class definition.            
This might even be              
the default actually.           
To be Class Definition          
might be on.                    
But there's other               
choices in here.                
And the one we choose the most  
often is Category/Extension.    
By the way, category just       
is the Objective-C word for     
extension.                      
Objective-C has something like  
extensions called categories.   
So that's why it says           
Category/Extension.             
But you can think in your mind  
that this just says extension.  
And what this is gonna do is    
only generate an extension      
of your Tweet class.            
You have to actually write      
the Tweet class itself.         
But it's all gonna have         
only your code in it, or        
it could be empty if you want.  
The extension's gonna take      
care of all making the vars.    
Okay, the var                   
magic right there.              
So let's see how this works.    
Even when I switch to           
Category/Extension.             
Again, I don't get that         
extension showing up in         
my navigator.                   
It's kind of hidden from you.   
Here I'm gonna add the          
extension way of doing it for   
TwitterUser too.                
So both of them, both Tweet     
and TwitterUser, I'm gonna      
have an extension generated     
and, why do we like this one?   
Because, a lot of times for     
our Tweet or TwitterUser we     
want to add our own code.       
Like in a tweet.                
Imagine you wanted to add       
a static method that took data  
from Twitter and turned it      
into a tweet in the database.   
Where would you put that code?  
Well, a great place to put it   
would be in a tweet class,      
if there was such a thing.      
And so, you're in fact,         
going to create such a thing.   
And the extension is going to   
handle all of the var business  
for you.                        
If you did choose Manual/None,  
right here for Codegen,         
meaning don't do any Codegen,   
then you're doing value for     
set value for key.              
Good luck with that, the        
code's gonna be a mess, okay?   
So, we almost always do it      
this way with this extension.   
Also, if we build our app       
using multiple modules          
like we have in Smash Tag,      
we have a framework module and  
then we have the main module.   
Then you're probably            
gonna wanna choose              
from this pull-down here        
where it says module,           
current product module.         
I think if you have a single    
app that's not modularized      
like that you probably          
don't need to set that, but     
in a multi-modual app           
you probably do want to.        
So, since we've chosen here     
to create only the extension,   
we obviously need to write the  
code for the classes Tweet And  
TwitterUser, we have to create  
those classes ourselves.        
So how do we do that?           
Well, just like we              
create anything,                
we use file, new file.          
Then we do file, new file,      
this time we are back           
to saying it's a cocoa touch    
class because NSManageObject.   
Why is it code called           
cocoa touch class,              
we wanna make sure we set       
our super class to be in its    
managed object, right?          
So, I'm creating                
a class called Tweet,           
you see, which is a subclass    
of NSManagedObject.             
And is gonna create this for    
us.                             
See?                            
Class Tweet: NSManagedObject.   
No code in there.               
That space is for us,           
we get write anything we want.  
The code that does the vars     
is in that extension which we   
don't even see, but but         
I'm gonna show it to            
yo in a second here.            
Notice that I picked            
the name of this class Tweet    
to be the same as the name of   
the entity in the database,     
which, you want to do.          
It is possible to not do that   
by inspecting the entity        
in the data model,              
but, don't do it.               
Just have the entity            
with the same name.             
People reading your code are    
going to expect this class,     
this subclass of                
NSManageObject that             
represents a tweet.             
Entity to be called tweet,      
so called it that.              
Now, we've got an error here,   
I'll just created this class,   
how I'm gonna possibly          
have an error,                  
I'm done anything how could     
I've done anything wrong?       
Well, the problem               
the problem here is,            
really, Xcode has               
done something wrong.           
When Xcode created this,        
it didn't seem to realize that  
NSManageObject is               
not in UIKit.                   
You see how it put              
import UIKit at the top?        
Really, what we need there      
is import CoreData, okay.       
All the code that you write,    
any time you're doing           
something in CoreData,          
you have to import CoreData.    
It's a different framework      
that the UIKit so               
you must import it everywhere   
that you're going to use it.    
Just like we had to import      
Twitter everywhere we want to   
use that Twitter framework      
that I gave you.                
So, I don't know why Xcode,     
I think it's just an oversight  
Okay?                           
that Xcode when you             
choose NSManagedObject          
as your super class you should  
know, that's in Core Data so    
it should be import             
Core Data there.                
Don't know why it               
doesn't do that.                
So here I've created one for    
the TwitterUser class.          
Again you can put anything      
you want in there.              
This is your class.             
You can do anything you want.   
All the stuff about             
the vars is off in              
an extension somewhere.         
In fact, let's go take          
a look at that extension,       
Even though it's not going to   
show up in your next navigator  
what it looks like.             
you're probably never           
going to look at it.            
I thought I'd                   
show it to you so               
you understand a little         
bit what's going on.            
So, this is the extension,      
this generated for              
TwitterUser.                    
You see that is an extension    
of the TwitterUser class,       
right?                          
Remember extensions and         
it's got the vars.              
They're defined not just        
name and screenName but         
it's got that relationship      
var tweets as well.             
All right?                      
And look at                     
the type of tweets.             
As promised, it's an NSSet,     
it's an optional because it     
comes out of                    
the database as not set.        
It's gonna get set.             
So these are the vars.          
And I'll talk                   
a little bit about              
how these vars are actually     
implemented in a minute but     
all the vars are there.         
There's also some functions,    
now at the bottom you           
see those functions,            
those are kind of fun, those    
are convenience functions for   
adding and removing tweets      
from the tweets set             
because NSSet is immutable,     
okay?                           
It's not var verses             
let like swift things,          
NS set is kind of old           
Objective-C way, and NSSet,     
like NSAttributedString, is     
immutable, cannot be changed,   
so how can I add any tweets     
to my database here?            
Well you used these functions   
instead, add to tweets,         
remove from tweets,             
add to tweets,                  
remove from tweets, there's a   
pair for doing a single tweet,  
and there having adding         
a whole bunch of tweets, or     
removing a whole bunch          
of tweets, okay?                
So you're definitely going      
to want those functions for     
your assignment five.           
Cuz you're gonna have some      
relationships where you're      
gonna want to add them          
using these functions.          
Now it adds those               
functions for                   
any too many relationship, any  
time you have a too many var    
like tweets, it's going to add  
these functions automatically   
It actually put it in its own   
little extension, this file     
in the extensions.              
has two extensions in it,       
both through TwitterUser.       
Any questions about extensions  
there or any of that?           
Okay, let's look at tweets      
extension real quick.           
Couple other things to look     
at here that I didn't look      
in the other one.               
Notice this static func         
called fetchRequest?            
Put that in your mind.          
I'm gonna talk about            
that in a few slides.           
fetchRequest is a really cool   
little static func that will    
give you something you          
can use to fetch tweets.        
And if you call fetchrRquest    
on twitter users,               
you'll get something to         
fetch twitter users.            
And we'll talk about all        
about fetch in a moment here.   
Notice the type of tweeter,     
see the tweeter var.            
Its type is TwitterUser.        
Because of course that's        
what the tweeter is,            
we control drag between the     
tweet and the tweeter user so   
that tweeter var is of          
course a tweeter user,          
not an NSSet, because it's      
a two one relationship, okay,   
there's only one TwitterUser,   
who is my tweeter.              
And what about                  
this @NSManaged?                
Okay, @NSManaged I'm just       
gonna say it's magic.           
It's not really magic.          
It's essentially something      
that says to the runtime, hey.  
When someone                    
accesses this var,              
Core Data's gonna               
figure it out for you.          
And what Core Data does,        
is when you try to say          
Tweet.created equals some       
date, it gets trapped           
at a low level in the runtime   
and Core Data swoops in and     
does set value for              
key for you, okay.              
Same thing if you get the       
created var, it swoops in and   
does value for key and          
gets it that way.               
But it's all happening at       
a low level behind the scenes.  
So this extension does satisfy  
the extension limitation where  
it can't have any storage.      
All of the storage for these    
vars isn't in the database.     
And when you ask for it.        
Or when you set it,             
it's using its value for        
key instead of value for key,   
to set it in the database.      
Now again, it sets in memory.   
You have to save it for         
it to actually go out           
into the database.              
But that what's happening.      
All right, so                   
now that we have these          
class so here's some            
code that creates a tweets and  
sets it's attributes, okay so   
let's look at this piece by     
piece and see what it does.     
The first thing is to create    
a tweet, we don't have to do    
NSEntityDescription, Entity,    
insert Entity for name into     
contacts, or whatever that      
huge, long terrible thing was-  
we can just say, tweet,         
parenthesis context.            
You just say what context,      
which means what database you   
want the tweet to put in and    
it creates a new tweet.         
Okay, just use a normal         
initializer for                 
new things so                   
that's super cool.              
That's one of the coolest       
features right there.           
Not having to use an            
NSEntityDescription thing, so   
no more NSEntityDescription,    
we'll not have to do that.      
And then here,                  
I'm setting the text to be      
140 characters of pure joy.     
And I don't have to say set     
value 140 characters of pure    
joy for key text and have all   
these literal strings like      
text in there in                
this untyped thing.             
I just say tweet.text           
equals that.                    
And the same thing here with    
created, again, so we don't     
even have to worry about        
the thing, if we tried to say   
tweet.created equals quote      
hello, this Swift would say,    
no, created is of type Date,    
so you can't do that, so        
it finds all of our,            
it type checks everything,      
finds all of our                
possible errors.                
What about relationships,       
okay, setting relationships?    
So here I've created another    
object, a TwitterUser and       
again I just set                
TwitterUser with a context,     
I'll talk about that argument   
in just a second but            
I told what database I wanna    
create in TwitterUser and       
I set my tweet's tweeter        
equal to that TwitterUser.      
So, it's exactly what you're,   
would imagine right?            
Just set it equal to Joe.       
And what's interesting about    
this is that when you set one   
side of a relationship,         
the other side gets updated     
automatically, 100%             
of the time.                    
This is call maintaining        
the integrity of the database,  
okay?                           
And Core Data always            
maintains database integrity.   
So, when you change             
one side relationship.          
It changes the other.           
So, that means for              
example if I say tweet.tweeter  
equals Joe, then if I went      
over to the Joe side and        
said hey give me Joe's tweets   
and I'm even gonna turn it      
into a Swift kind of set        
from an NSSet to a set of       
tweet because we know that's    
what tweets are, right?         
Tweets are a set of Tweets, so  
I'm gonna as it to do that.     
Then I can say, if Joe's tweet  
contains that tweet print yes   
and of course it is             
going to print yes.             
Because when I said             
tweet.tweeter = joe,            
it automatically got            
added to joe's tweets.          
That make sense?                
And same thing the other way.   
If I added a tweet              
into joe's tweets,              
that tweet tweeter would        
automatically set to be joe.    
Okay?                           
Both sides will always          
point to each other.            
You never have to do anything   
to make that happen.            
tweet.tweeter=joe is exactly    
the same as saying joe          
dot addToTweets tweet.          
Remember addToTweets is one of  
those convenience functions     
that it created for             
us over there.                  
Now, notice                     
the argument I used for         
the context to create           
the Twitter user there.         
I didn't say                    
AppDelegate.viewContext.        
I didn't use that same          
context bar that I had.         
I said                          
tweet.manageObjectContext.      
In other words, I got, I found  
out what database the tweet is  
in, and I put the Twitter       
user in the same database.      
And this is a common way        
of programming in Core Data     
where when you wanna            
get a context and               
you already have a object       
in the database you             
ask the object you already      
have what context to use.       
And you can see that if I ever  
change my code to not put this  
into this context, to put it    
into another context, at least  
the Twitter user and the tweet  
would always be together        
in whatever that context is.    
So you can see why I            
used the tweets can't           
manage object context here to   
create that instead of using    
the context again.              
So, it, it would work to        
say context, of course,         
but I'm just saying there's a   
paradigm of development where   
we're gonna try and use         
the context of related object.  
So they end up in the same      
database for sure.              
Okay?                           
All right, so                   
we can also use dot notation,   
because these are just vars.    
So when I say tweet.tweeter,    
I get a TwitterUser object.     
So, of course,                  
I can say dot name on it and    
set it equal to Joe Schmo,      
whatever, right?                
tweet.tweeter.name =            
"Joe Schmo", all right?         
No restriction there            
on those vars.                  
All right, remember I told      
you about the scalars?          
This is that switch I was       
telling you about before.       
If you don't do this,           
then when you say,              
if you had an int,              
let's say you had retweet       
count which was an int          
here let's say on Int32.        
If you don't switch             
this button,                    
then that's going to be         
an NSNumber not an Int32.       
But when you click              
this switch on,                 
now that var will               
be of type Int32.               
So you almost always            
want this for numbers.          
99.9% of the time, you want     
to have this switch on.         
Luckily, it's on by default so  
you don't even have to          
think about it much, but        
I just wanted to let            
you know about it.              
All right, so                   
now lets talk about deletion.   
Okay, now, I want to delete     
something from the database.    
And that's incredibly easy,     
almost too easy because your    
data's precious you don't want  
to be deleting it to easily,    
but you do that by asking       
the context to delete the       
NSManagedObject, so you can     
pass any NSManagedObject        
to this method delete and       
it will delete it               
from the database.              
And it could cascade and        
delete other things as well     
depending on what delete        
rule is, all right?             
Most of the time by default,    
when I delete something,        
other things that point to it   
get that pointer set to nil.    
That's the nullify              
delete rule.                    
Now, when things get deleted    
from the database they got      
sent this message first,        
prepare for deletion.           
Okay, and                       
this is a really good method.   
Again, in here you don't        
have to do anything             
to worry about the other        
pointers point to you           
that's all fixed by             
the delete rule.                
But what if you had another     
field in your database?         
Back to the retweet             
count example again.            
Let's say I had an int          
somewhere in TwitterUser,       
which counted                   
the number of retweets          
that this twitter               
user had done.                  
And so if I was deleting        
a tweet and it happened to be   
a retweet then I need to set    
that to be minus equal one.     
And here's the perfect          
place to do it.                 
So tweet, and                   
it's prepared for               
deletion saying whoop,          
I'm about to be deleted.        
I'd better tell my Twitter      
user, cuz I'm a retweet,        
that he needs to decrement      
his retweet count.              
So you see why you would        
use prepare for deletion?       
It's a way to kind of update    
other things in the database    
when as you're                  
leaving the database.           
All right, so                   
that's it for deletion.         
Next topic, querying,           
the most important piece of     
this whole database thing.      
It's really a waste of time     
doing all this stuff if you're  
not gonna query, okay?          
If you're not gonna make        
sophisticated requests for      
the information based on        
the relationships, etc.         
So, to do a query the most      
important thing you need to     
know is NSFetchRequest,         
this class NSFetchRequest.      
And NSFetchRequest              
encapsulates                    
what you want from              
the database.                   
So let's talk about             
an NSFetchRequest and           
how we build one.               
So when we're building one,     
there's three important         
things we need to know.         
One, what entity                
are we fetching?                
Because a FetchRequest can      
only Fetch one kind of entity.  
You can, there's no such thing  
a FetchRequest that will give   
you some tweet and              
some Twitter user.              
No, okay?                       
A fetch always gives            
you all tweets or               
all Twitter users, make sense?  
So that's the number            
one thing,                      
is we're gonna create           
the fetch request.              
And it will be a fetch request  
or a very specific entity.      
And it will only be able        
to fetch those entities.        
The second thing is is          
an array of sort descriptors.   
And why do we want this?        
Because when we execute this    
fetch it's gonna come back      
as an array, okay?              
All the matching tweets or      
Twitter user will come          
back in an array.               
And since it's an array,        
arrays are not sets,            
arrays are ordered and so       
we have specify what order      
the things are in the arrays.   
So we do that with              
these sort descriptors.         
And finally, we just specify    
or what is it that we want,     
which tweets do we want, which  
Twitter users do we want and    
we do that with something       
called a predicate.             
Okay, so let's dive in and      
look at all three               
of these things.                
This is what it looks like,     
kinda top level to              
create a fetch request.         
Okay, you get a fetch request.  
You set the source descriptor   
and you set its predicate.      
So you get each of              
these three parts.              
So getting the fetch            
request is easy.                
We're gonna use that            
little static function          
that the extension that         
I talked about, made for        
us called fetchRequest.         
Now, this is one of the very    
few times when Swift            
cannot infer the type           
of this return value.           
Should've put this in red,      
okay?                           
Because it's so                 
rare, Swift can almost          
always infer things.            
But in turns out                
NSManagedObject                 
has a fetchRequest method and   
it returns the more generic     
kind of fetchRequest and        
so when you're getting it,      
it doesn't quite know           
which one you want.             
So when you ask a Tweet for     
its fetch request right here,   
you have to tell it did you     
want the one in Tweet not       
the one from its super class?   
All right?                      
And so                          
say let request equal           
NSFetchRequest.                 
It's a generic type like array  
or something like that, right?  
This is a fetch request         
only for Tweets.                
So you say                      
NSFetchRequest =         
Tweet.fetchRequest().           
And it knows, of course,        
that the only one that          
returns an NSFetchRequest for   
tweets is the fetchRequest,     
and that's Tweet extension.     
So now,                         
you have a fetchRequest,        
this is how you get a fetch     
request- couldn't be easier.    
You just have to remember       
to do that static               
typing right there.             
Okay, now we need               
the sortDescriptor, right?      
It's got this                   
array coming back.              
What order are they             
going to be?                    
SortDescriptor looks            
like this.                      
You create it with a key.       
That is the key,                
the attribute in                
the database that you want to   
sort on, so the screen name or  
even the text in the tweet or   
the actual name of              
the tweeter,                    
whatever it's gonna be.         
This right here,                
sortDescriptor,                 
will be a sort descriptor only  
suitable for fetching Twitter   
users, because screenName       
is a key in Twitter user,       
not in tweet, so we're gonna    
use this SortDescriptor         
in a tweet request.             
And I say that because          
on the previous slide,          
I just showed you how to make   
a fetch request for a tweet.    
Anyway, I should just, that     
should have been Twitter user.  
But anyway, so                  
this is a Twitter user.         
SortDescriptor.                 
And notice it has ascending or  
descending like us A to Z or    
Z to A and then it has          
this argument selector and      
this one creates                
some confusion.                 
But really this                 
selector just says,             
what method am I gonna use to   
compare items to do the sort.   
All right now, you don't even   
have to specify the selector    
if you don't want to and for    
almost all data types,          
numbers,                        
dates, it's going to use        
a method called compare, okay.  
Compare returns something       
called a comparison result      
which is either, it's the       
same, it's greater than, or     
it's less than.                 
So, that's what this            
compare method does.            
And it's implemented by date.   
It's implemented by Int32.      
It's implemented by double.     
It's even implemented           
by string.                      
Okay?                           
So,                             
you could just use compare.     
But, for strings.               
You wanna think a little        
bit about what kind             
of comparison do you want?      
Do you want                     
case-insensitive compare?       
Or you could even use           
this special compare,           
called                          
localizedStandardCompare.       
This will compare them so       
that it is sourced just         
like the finder on the Mac.     
And what does the finder on     
the Mac do that's different     
than case insensitive?          
Well, there's a lot of issues   
with things like diacritic      
marks, and you know,            
things in your local language   
where things sort differently,  
depending on what language      
you're in, what locale it is.   
You'd, you sometimes you        
ignore the diacritics,          
like accent marks.              
Sometimes they mean something.  
And, so localized standard      
compare is a special compare    
for strings, that knows         
how to do that, okay?           
And this is very commonly the   
one we will use for strings.    
When we're gonna show           
something in our UI,            
maybe this array of thing for   
fetching,                       
we're gonna put it in the UI.   
We would want it                
to be in order,                 
this localizedStandardCompare.  
You notice that it's            
an NSString dot method.         
It's not                        
String.localizedStandardComp-   
that's because this has to be   
an Objective-C visible method.  
are.                            
And                             
And you need                    
the NSString version.           
So basically you're going       
to say NSString dot, and        
you can go look, search for     
compare in NSString or string,  
because a string implements     
them all as well but            
you need NSString dot and       
then the name of the method.    
And you can search, and         
there is case insensitive and   
the standard compare and then   
the regular compare and etc.    
Now one other thing             
about this is that,             
these methods some of           
them are special in that,       
it does to compare on           
the database side, okay.        
Using SQL to do it,             
see what I'm saying?            
It's not actually bringing      
all the data over.              
Calling this method             
on every string, and            
doing some kind of              
quicksort or something.         
It's using super powerful       
sorting mechanisms that         
are built into an SQL           
database, okay.                 
So, in fact, all of the         
NSString ones will do that.     
Okay, so                        
they're super duper efficient.  
Now, if you wanted to use       
your own compare though,        
it's not gonna be efficient.    
Because it is gonna have to     
bring all the data from the     
database into your memory so    
it can run your little          
method over it.                 
So I strongly recommend         
against using your              
own selector here.              
I would use                     
the standard selectors.         
If you're gonna use             
your own selector               
it's gotta be on                
a pretty small dataset.         
Cuz it's not gonna              
be very efficient.              
Notice that when we             
do the fetch request,           
we don't just give it           
a sort descriptor,              
we give it an array             
of sort descriptors.            
That's the old sort by last     
name, and then first name.      
Right?                          
So if                           
we have 12 Smiths in there,     
we'll sort them and             
the Smiths will be              
in the right spot.              
And then all of the first       
names of the Smiths             
will be in order by that.       
So we can have as many of       
these sub sort by the one       
thing, sub sort by              
the next thing,                 
sub sort by the next thing.     
Basically, we can break ties    
with subsequent sorting and     
that's why we give an array     
of sort descriptors.            
Okay, so,                       
that's the fetch request and    
its sort descriptors and        
now the predicate.              
Okay, the predicate is the      
guts of saying which tweets do  
we want.                        
Which Twitter                   
users do we want?               
We create them with kind        
of interesting API.             
It looks a lot like             
printf from C.                  
NSPredicate format colon,       
and then a string.              
And the string is               
a format string.                
And again,                      
looks a lot like printf.        
So the best way to explain      
this is probably by example.    
But the way you're gonna        
learn this is you're gonna go   
read the documentation for      
NSPredicate, you've got to go   
read that documentation,        
in its class documentation,     
there's gonna be a link that    
says, creating predicates,      
or something like that, click   
on that, and go there, and      
learn all the things you can    
put in this format string,      
cuz it's all very specific to   
doing database queries, but     
I'll show you some examples,    
so                              
you get an idea of              
what's going on here.           
So here's the first one,        
let's have the search           
string called foo.              
All these searches then         
I'm gonna do right here         
are tweet searches.             
These are for predicates for    
searching for a tweet.          
So first, I'm gonna find        
all the tweets whose text,      
the actual tweet, the 140       
characters of pure joy or       
whatever, contains              
case sensitive.                 
Case insensitively.             
That's what [c] means.          
%@.                             
%@ is a substitution variable,  
and I have to give              
its value at the end.           
And so I'm substituting         
search string.                  
Okay, note that I can't say,    
text contains foo.              
I have to say,                  
text contains %@ and then.      
Put something at                
the end there.                  
Okay, so                        
that's an obvious one,          
I'm searching for all my        
tweets that contain foo.        
How about this one?             
I want all the tweets           
whose tweeter equals %@.        
I'm going to put Joe in there   
as the substitution variable    
and created after some          
date that I create.             
See that?                       
I'm using greater               
than to do that.                
And I'm doing && for and,       
you can also use the word and   
there.                          
Okay?                           
So that's all gonna be          
the tweets created by           
Joe since that date.            
You're starting to see the      
power of building the query     
into the database, right?       
If I had thousands of tweets,   
it'd be really easy to find     
the ones since yesterday,       
for example.                    
I'll show you that              
in a second here.               
Aand then I can also though,    
search through dot notation,    
on other fields,                
in other entities, but          
this tweeter.screenName equals  
percent @ sign%@ with CS193P,   
that's still searching for      
tweets.                         
That's searching for            
tweets whose tweeter's          
screen name is CS193P.          
Do you see what                 
it's doing there?               
This is still                   
a tweet predicate.              
This is not a twitter           
user predicate.                 
Okay?                           
So here's a different           
predicate.                      
This one is for Twitter user.   
So here I'm searching for       
all the Twitter users           
Okay?                           
who has a Tweet whose           
text contains foo.              
Okay?                           
So it even knows how            
to do a pluralistic             
search right here where you've  
got tweets dot text that means  
all the tweets, texts and       
doing contains and              
we can do [c] if                
we wanted foo.                  
So that's a twitter user        
search right there.             
the twitter users who have      
tweeted anything that includes  
We're looking for               
foo, again a powerful search,   
really easy to express.         
Question.                       
>> [INAUDIBLE]                  
>> So the question,             
does it infer this from         
the name of the variable,       
it's not inferring it,          
it's actually using the name    
of the attribute tweets         
right there and the name of     
the attribute text and it's     
building a SQL statement that   
will go and do this fetch.      
Okay now it's doing all         
that underneath the covers,     
we don't care how,              
but it's doing it.              
Yeah, compound predicate.       
You can build a compound        
predicate like an and           
predicate or an or predicate.   
You could put or or             
and in the string, or           
you could create separate       
predicates and and              
them together by creating       
an NSCompoundPredicate.         
And predicate with              
sub-predicates, and             
just given an array             
of predicates and               
it ands them together.          
Why would you ever want to do   
this versus just putting and    
or, or in there?                
Well, maybe you're computing    
what the predicates are,        
based on some, depending on     
what the user clicked on or     
something, you're               
computing it, and               
so you want to add these        
things you computed together.   
All right, there's also         
function predicates.            
Now these are super             
powerful predicates,            
and you don't need these for    
your homework, so               
don't worry too much about      
these, but they're cool.        
You can even say, you have      
a search like this one,         
tweets.@count > 5,              
this is a Twitter user search,  
that finds                      
all the Twitter users who have  
more than 5 Tweets, okay?       
So, @count is actually          
running, kind of a function in  
the database, to go count       
the number of Tweets that       
the Twitter user has.           
So, again, you'll see all       
of this when you go look at     
the NSPredicate documentation,  
it's incredibly powerful,       
you can see you barely have to  
type anything in as the format  
string, and you get these       
really powerful searches.       
All right, so let's put it      
all together now to create      
our fetch request, okay.        
I'm gonna create,               
in this case,                   
a Twitter user fetch request.   
So I'm saying                   
a FetchRequest =   
TwitterUser.fetchRequest(),     
then I'm gonna                  
create a time which             
was yesterday,                  
it's actually not,              
it's 24 hours ago.              
Time interval since now,        
minus 24 times 60 times 60,     
that's 24 hours ago, and        
I'm creating a predicate        
that says, find me any Twitter  
users that have a Tweet that's  
created before yesterday,       
or since yesterday I guess,     
yes, created is greater         
than yesterday.                 
So I'm finding all the Twitter  
users who have created Tweets   
in the last twenty-four hours,  
that's what this one does.      
So any is a special term        
that means match any            
of these things, and            
these things are Tweets that    
are created since yesterday.    
And I'm gonna sort the result   
by the actual name,             
the real name of                
the Twitter user.               
So I'm just doing               
sortDescriptor, key of name,    
ascending true, I'm not         
specifying a selector, so       
I'm gonna get kind of           
the default comparison.         
Okay, that's it, so that's how  
you create a fetch request.     
Now, since I have a fetch       
request, how do I make it go?   
Give me those Tweets,           
give me those Twitter users.    
We do that with the very        
simple method in context, so    
we ask the context to do the    
fetch, and it will go out and   
return an array of              
all those things,               
sorted in the way the fetch     
request says to sort them.      
Okay, simple as that.           
The only thing not so           
simple, it throws, okay?        
Just like context save throws,  
context execute also throws.    
So, you could put in            
a try question mark,            
in that case, if the execute    
fails, and usually it's gonna   
fail because your predicate     
is wrong, or something.         
Like your predicate just makes  
no sense then you could fail.   
If it's gonna fail,             
you're gonna get back nil,      
if you do try question mark,    
remember that's what try        
question mark means.            
It means try this, and          
if it fails, give back nil.     
But it if doesn't fail,         
then you're gonna get           
an optional array.              
And that array is               
gonna be empty,                 
if it couldn't find anything    
that matches your request, or,  
it's gonna be full of objects,  
okay?                           
Tweets, or Twitter users,       
an array of tweets, or          
an array of Twitter users,      
at least that's what it's       
gonna look like to you,         
it's not quite that,            
looks like it, all right?       
That's the result you're        
gonna get back, so, again,      
super simple querying.          
Now, you might be a little      
scared of doing this request,   
what if it's matches            
a million things, okay?         
Are you gonna get a million     
Tweets back in one              
request like this?              
The answer is no.               
This array that you get back    
is really super smart array.    
It doesn't actually bring       
the data in from the database,  
until you start asking for      
it, okay?                       
So until I ask for              
the Twitter user,               
a certain Twitter               
user's information,             
the Twitter user's name, the    
Twitter user's screen name,     
the Twitter user did not get    
faulted from the database.      
This is called faulting, okay?  
And so, these objects,          
you can imagine,                
they're kind of shells,         
empty shells.                   
And until you crack             
open the shell and              
start looking inside,           
it doesn't actually             
get the data for you.           
And the reason this             
matters to you is,              
if you go in the debugger,      
or you do a print statement,    
like this one where you say,    
for user in recentTweeters      
fetched user whatever,          
when you print that out,        
it's not gonna print the,       
a Tweeter user object,          
it's gonna print some           
kind of faulting shel.          
Because you haven't             
actually asked for              
any of the data inside          
that thing yet, so              
it hasn't faulted yet.          
But if you say, for             
user in recentTweeters and      
say fetched user named, and     
now you say user.name, now you  
are faulting this object in.    
In fact, this for               
loop would fault all these      
objects in to memory.           
Okay, fetch them all,           
cuz you're asking for           
the name of every single one.   
Boom, fault, fault, fault,      
they're all coming in.          
Now, it doesn't do it one by    
one, it faults in batches,      
it's really high performance,   
so,                             
you know,                       
don't worry about that.         
But just, I just don't          
want you to be surprised        
when you go in                  
the debugger and                
you're like, I printed out      
this Twitter, user and          
there's no screen name,         
what's going on?                
Well, it hasn't faulted it in.  
In fact,                        
the debugger you could say,     
print the user.name,            
and it would fault it in,       
okay, give it to you.           
All right, I told you I was     
gonna talk about Core Data      
thread safety, so here it is.   
NSManagedObjectContext,         
the context thing,              
that thing that you're          
sending executes to,            
that thing that you're hitting  
save, the things that you're    
using to create Tweet,          
Tweet, subcontext,              
colon whatever, that handle on  
database is not thread safe.    
A context can only              
be used on the queue            
that it was created on,         
period.                         
If you past a context           
to another queue,               
like you tried to               
dispatch off to some            
global concurrent queue, and    
you pasted the context, or      
even just pasted a Tweet,       
okay, that's not gonna work,    
cuz that Tweet was created      
on this other context.          
So in fact,                     
not only the context,           
but everything that you         
create on that context          
has to all be done              
in the same queue.              
So now you're                   
probably thinking,              
well how the heck do I          
do multithreading then?         
Cuz a database especially,      
you can imagine, for            
temple one to load your         
database off the main queue,    
cuz you, you might be loading   
lots and lots of things.        
Now your queries,               
your probably gonna do those    
on the main queue because,      
the user's looking              
at that information.            
You want it to be               
highly responsive.              
Okay, it's probably worth,      
and core data is super fast,    
especially with queries.        
So, you could probably do       
that on the main queue.         
But loading it up,              
you probably don't              
want to do that.                
All right, so,                  
how do we do multithreading?    
Although that we do             
multithreading in Core Data,    
is each database can have       
multiple contexts, okay?        
So, the database underneath,    
is multithreaded,               
it can have multiple            
contexts writing to it.         
Okay, completely                
different context,              
writing to the same database,   
in different queue's even, so   
it's fully multithreaded.       
So that means we had to have    
a context for every queue.      
Whatever queue we're going      
to access the database,         
we have to a context            
in every queue.                 
Now I'm gonna show you how      
to create a context, or         
on another queue, so            
you can do something with       
that queue in a second here.    
But first I want to talk        
about this important            
method in context               
called performBlock.            
performBlock just               
takes a closure,                
a closure that                  
takes no arguments,             
returns no arguments, and       
it will ensure, this is         
an insurance method, it will    
ensure that everything inside   
that closure happens on the     
right queue for that context.   
Okay, so this,                  
don't get confused,             
this method does not dispatch,  
you know,                       
cause background thrading,      
this is just making sure that,  
that closure executes           
on the right queue.             
So this is a way that           
you can kind of be safe.        
And some might argue you        
should put performBlock around  
every single call to every      
Core Data thing you ever do,    
because that will ensure that   
you'll never have a problem     
where you're accessing          
the context not on it's queue.  
Okay, it accidentally,          
you got some bad code.          
Now, that might be a little     
bit overkill especially if      
you're mostly using             
the main queue anyway, and      
you really, maybe you only      
use background queues for       
this tiny little bit of         
processing on the side.         
It's not like you have          
the tons context and            
lots of different queues        
all going at each other.        
So, it might be overkill.       
But if you're doing             
anything where you have,        
truly have multiple context     
on multiple queues and          
they're access and things,      
this is a good way to be safe.  
Okay, so all this does is it    
makes it so you are safe.       
The code inside that block      
will be executed on the proper  
queue for that context.         
Even if it has to dispatch,     
it will do it if it has to.     
If it doesn't                   
have to dispatch,               
if you're on the right queue,   
it'll just execute it, fine.    
But if you're on the wrong      
queue right now and             
you execute this,               
it will dispatch it             
to the right queue.             
There's also                    
performBlockAndWait,            
which will get it on            
the right queue and             
wait until it's done, and       
then continue in your queue.    
Okay, but this doesn't          
really talk about,              
how do I get another context    
in a different thread, right?   
I wanna do some code            
on another thread.              
Where do I get a context?       
The only context I know how to  
get right now is viewContext.   
That's the main                 
queue's context,                
that's the only                 
only one I can get.             
Okay, well, you're gonna        
use this really cool method     
in persistentContainer.         
This is new in iOS 10 and       
a really cool method,           
super cool.                     
It makes it really easy to      
do background process on        
Core Data.                      
It's called                     
performBackgroundTask.          
Remember, this is a function    
on persistentContainer that     
you get from the AppDelegate.   
And this takes a closure.       
This closure has one argument,  
the argument is a context.      
And that context is             
appropriate for use             
on this other thread that this  
is going to create for you.     
So this performBackgroundTask   
finds another queue,            
not the main queue,             
some other queue.               
And it creates a context        
in that other queue, and it     
executes your closure on that   
other queue in the background.  
Now, it's                       
a convenience method.           
So if you really needed         
to control the quality of       
service, for example, the       
queue and all the, okay, well,  
you can't use this.             
But 99.99% of the time,         
whatever quality of             
service that queue is           
getting is the right one for    
Core Data cuz Core Data         
knows its business.             
So you're gonna do it.          
Now, inside this closure        
couple of things really         
be careful of.                  
One, never use                  
viewContext in here.            
Do you see why that would       
be horrendously bad to          
use viewContext                 
inside this closure?            
Because this closure by         
definition is not executing on  
the main queue.                 
By definition this              
closure is on a separate        
queue on a background queue.    
That's the whole                
point of this thing,            
is to put this thing            
on another queue.               
So never use                    
viewContext in there,           
that's why it's in red, okay?   
The second thing is don't       
forget to save this context.    
If you do a whole bunch         
of stuff in here and            
you don't save,                 
you just did for                
nothing cuz you did in memory.  
And then this block went away,  
you're never gonna get that     
context back again,             
that data is lost.              
Which all gonna leave the heap  
and then nothing ever happens.  
It never gonna get              
committed to the database.      
So, don't forget to             
save before you leave.          
Now, when you save,             
it will push it down            
to the database and             
your other context like your    
viewContext will see it, okay?  
And so these two contexts, the  
one that's happening on this    
background and                  
the viewContext.                
They're working on              
the same database, so           
when this one saves,            
boom this guys is gonna         
start seeing those changes.     
I'm gonna talk a little bit     
how react to seeing those       
changes in a minute here.       
Okay, so,                       
everyone understand this?       
Cuz you're gonna have to        
do this in assignment five.     
And I want you to do all your   
loading off the main queue,     
and all your fetching           
on the main queue.              
All right, Core Data is huge.   
Huge.                           
I can't cover it all.           
It's got optimistic locking,    
for                             
those of you that               
know about database.            
It's got optimistic locking     
and all that database stuff.    
It has full undo, redo,         
which is incredible.            
It obviously knows how to       
roll back unsaved changes.      
Okay, if you have               
changes in memory and           
you want to roll                
some of them back,              
you can do that                 
before you save.                
It knows about staleness,       
like, if I make a fetch,        
how long before I really wanna  
fetch it again because I don't  
trust that the data             
hasn't changed, right?          
How long it takes for           
the data to get stale.          
And a lot of other              
things in the Core Data.        
So, I can't cover it all,       
there's not enough              
time to do that.                
Cuz we're trying to talk about  
a whole another topic about     
But you'll want to check the    
documentation, you won't need   
Core Data here.                 
anything else of this stuff to  
do your homeworks, of course,   
I'm just trying to get          
you started with this.          
But you need to know that this  
stuff is in there, so that      
one day when you go out and do  
some significant iOS database   
stuff, you'll know that these   
features are out there.         
All right, the next topic here  
is Core Data and UITableView.   
As you can imagine, this is a   
marriage made in heaven, okay?  
Because you got this database,  
got all this big data           
sets in there and               
what is the UI we use to        
show big data sets in iOS?      
UITableView.                    
Okay, UITableView is great      
at showing arbitrary large      
data sets in our                
arbitrary UIs, right?           
We can do custom                
table view cell,                
we can do anything UI we want.  
So, this is so common that      
Apple has invented this very    
important class called          
NSFetchedResultsController.     
This is not a viewController,   
okay?                           
This is a controller that       
controls Core Data and          
UITableView talking together,   
but it's not in its fetch       
results view controller, okay?  
And all this                    
NSFetchedResultsController      
does is it hooks up an          
NSFetchRequest that you create  
to a UITableView.               
And it hooks them up in such    
a strong way that if anything   
changes in the database that    
would cause that fetch request  
to return different results,    
it updates the table            
automatically, you don't        
have to do anything.            
So this is an active            
live hookup between             
the NSFetchRequest and          
the TableView, okay?            
Even if some other context are  
changing the data, it doesn't   
matter, it's always keeping     
that TableView up to date.      
So I'm gonna talk               
about how we do this,           
how we use                      
an NSFetchedResultsController.  
I'm even gonna provide you      
some kind of free code          
to do some of it.               
You'll have to type in a        
little bit of the rest of it.   
But it's,                       
it's pretty easy to do.         
So how fundamentally does       
NSFetchedResultsController      
work?                           
Two ways, one,                  
it has a delegate and           
that delegate you set to be     
your UITableViewController.     
And whenever the                
FetchResultsController sees     
something happening             
in the database that would      
affect that fetchRequest,       
it tells the table view         
controller, hey, do this,       
add this row, add a section,    
reload this row, whatever,      
it uses UITableView primitives  
to update the table, okay?      
I'm gonna show you,             
I'm gonna give you the code     
that does that part of it,      
that implements the             
NSFetchedResultsController's    
delegate, okay, so              
that's one way it does it.      
The other way that              
the NSFetchedResultsController  
works is that it provides       
implementation for              
all of your UITableView data    
sources methods, right?         
Because the contents            
of your table                   
are coming out                  
of the database,                
so NSFetchedResultsController   
lets you know all of them, how  
many sections, how many rows    
and sections all that stuff.    
In fact,                        
this is what it looks like,     
this is the implementation      
that you're gonna put in to     
your controller when you have   
fetchedResultsController.       
The first thing you're gonna    
do is you're gonna create a     
fetchedResultsController, and   
I'm gonna show you how          
to do that in a moment.         
And so you're always            
gonna have a var called         
fetchedResultsController, and   
it's gonna be of type           
NSFetchedResultsController.     
And when you have that var,     
now you can implement your      
sections, number of sections    
in TableView by saying return   
fetchedResultsController        
.sections.count, okay?          
Those are a lot of              
optionals in there, so          
we'll default to one section.   
And then to get the number      
of rows in a section,           
you're just gonna say the,      
you're gonna get                
the sections first by saying    
fetchedResultsController?.sec-  
tions.                          
And as long as you have some    
sections, sections.count        
greater than zero, then you're  
gonna return the sections in    
that section that's passed      
to you number of objects.       
Okay, so that code, that's it,  
that's all of your, those two   
methods, that's the entire      
implementation if you're using  
a fetchedResultsController,     
okay?                           
And then of course,             
there's cellForRowAt, okay,     
you gotta implement that,       
that one too,                   
you're gonna use                
fetchedResultsController.       
And the most important thing    
about cellForRowAt is you need  
to know what's at that row,     
which thing in my database is   
at that row in that             
section in my table.            
And you get that by asking the  
fetchedResultsController with   
this method objectAtIndexPath.  
So you just say                 
fetchedResultsController,       
give me the object, and that    
object is gonna be a tweet, or  
a Twitter user, or              
whatever, some entity.          
Give me an object               
at the index path               
that cellForRowAt               
indexPath is asking me for.     
So now I have the Twitter       
user or the tweet,              
I can easily load up my UI.     
You know, pass it off to my     
UI, custom UITableView cell,    
or if I have a subtitle cell,   
just take a couple of           
things out of there and         
put it in the text label        
in the detailed text label,     
you see what I'm saying?        
But you can see that            
the fetchedResultsController,   
that code in yellow right       
there in the middle of          
cellForRowAt indexPath,         
that's doing all the work       
to figure out what tweet or     
what Twitter user is at this    
row in the table, okay?         
So those code on                
the last slide and              
the code on this slide, you'll  
have to type that code in any   
time you're using               
an NSFetchedResultsController.  
Now, on the previous slide,     
one of the things was var       
fetchedResultsController        
equals something.               
So now let's talk               
about how we create             
a fetchedResultsController,     
okay?                           
So this is what                 
the initializer for             
NSFetchedResultsController      
looks like here.                
It takes a request, a context.  
Obviously, it doesn't           
know what database              
we're fetching in.              
And then it's got               
a sectionNameKeyPath.           
That sectionNameKeyPath         
is the var in                   
that entity that,               
whose value is a string,        
which is the title of           
the section it's in, okay?      
That's how you do sections      
with fetchedResultsController.  
You just have to, and you       
might have to invent this or    
even calculate this.            
But all of your tweets or all   
your Twitter users, if they're  
gonna be in sections,           
they all have to have a var,    
which is a string, which is     
the section they're in, okay,   
the name of the section         
they're in.                     
And as long as they have that,  
then the fetchedResults will,   
will make the sections and      
put them all in there           
in the right section.           
And we'll talk about            
cacheName in a second here.     
So we have to create            
a fetchRequest to put in here.  
So here's an example of         
creating a fetchRequest for     
tweets, right?                  
So you recognize that           
first line there,               
creating a fetchRequest for     
tweets.                         
And I'm gonna sort by when      
the tweets were created, okay,  
when the tweet                  
was tweeted out.                
And I'm gonna look for all the  
tweets whose tweeter's name     
equals some name,               
the name, okay?                 
So it's gonna get all           
those tweets, and               
I'm gonna set that request      
as the first argument there,    
to NSFetchedResultsController.  
By the way, notice              
NSFetchedResultsController is   
also a generic type, and        
NSFetchedResultsController can  
only control fetches for        
a certain type.                 
So you have to say what type,   
okay, what type of entity that  
your FetchController is doing,  
and these are the same type of  
things that are in              
the rows of your table.         
Now that cacheName at           
the bottom is interesting.      
That is actually going to       
permanently cache the results.  
it's gonna get the results      
out of the database and         
In other words,                 
store on disk the result        
in some internal format.        
And that's cool, and            
that storage, by the way,       
if you quit your app and        
come back,                      
it will still use that cache,   
so it's quite efficient.        
But you have to be              
a little bit careful.           
You cannot change anything      
about your request.             
As soon as you change anything  
about your request, like        
the name, the tweeter.name      
that you're searching for, or   
what you're sorting by,         
or anything.                    
Now that cache is invalid, and  
you'll have to invalidate that  
cache, okay, and there's an     
API in there for doing that.    
You can pass nil there if you   
don't wanna do the caching,     
which for most reasonable       
sized datasets perfectly fine,  
you don't really                
need the caching.               
But I just wanna emphasize      
that if you change your         
request, your cache             
is now invalid.                 
And about that section key      
thing, something to be careful  
about there, too, is that       
whatever your sortDescriptors   
say that your rows would        
sort in, that has to be         
exactly the same order that     
your sections was sorted in.    
In other words,                 
the FetchedResultsController    
doesn't know how to             
like move things around         
because they sort out of        
order of their sections.        
That's why a lot of times       
that we're doing sections,      
the first sortDescriptor will   
be sort by the section key      
name var, right?                
And then the second one         
will be sort by what we         
really wanna sort by,           
because we have to make sure    
that our entire table is        
sorted in section order.        
You see why?                    
Cuz otherwise it's just weird,  
things would all be             
in the wrong places.            
So                              
keyThatSaysWhichAttributeIsTh-  
eSectionName has to sort        
in the same order as your       
sortDescriptors.                
Okay, now, I told you that      
NSFetchedResultsController      
watches Core Data.              
It sees changes happening in    
there, and it updates it.       
And it does that with           
its delegate, okay?             
Its delegate wants              
to be the tableView,            
be the tableViewController,     
rather.                         
Cuz it's gonna tell             
the tableViewController, and    
it sends messages like this.    
So this is a typical            
NSFetchedResultsController      
delegate method.                
Controller did change add       
indexPath for change type, and  
here's the new indexPath.       
Okay, and these change          
types might be deleted or       
inserted or                     
modified or whatever.           
Now, you have to put the code   
in there that would call        
the right methods on the        
tableView to get the sections   
inserted or deleted or          
rows added or whatever.         
But I'm gonna give you that     
code for free, okay, and        
the demo that I'm               
gonna do on Wednesday,          
I'm gonna have a class called   
fetchedResultsTableViewContro-  
ller, which is                  
gonna be a class.               
And you can make that to        
be the super class of your      
UITableViewController.          
And you'll just inherit         
this implementation of          
the delegate, okay?             
Yes, cuz that's                 
what I just said.               
Okay, so when you're using      
core data in UITableView,       
the things to remember are,     
you're going to subclass        
fetchedResultsTableViewContro-  
ller,                           
the thing I'm gonna give you,   
so that you implement           
NSFetchedResultsController      
delegate.                       
You're going to add a var to    
your UITableViewController      
called                          
fetchedResultsController, and   
you're gonna set                
its value to be                 
an NSFetchedResultsController   
with the fetchRequest that you  
want, okay, that you want       
to populate your table.         
Then you're gonna implement     
your UITableView data source    
methods using                   
fetchedResultsController var    
methods, just like I            
showed you in the slides,       
character for character,        
you can use the exact same      
things that are on the slide.   
Okay, and then it's all gonna   
magically work, all you'll      
have to do is inside your       
cellForRowAt indexPath,         
you'll have the object,         
the tweet,                      
or the Twitter user, you        
just gotta load up your UI.     
After you have                  
all this set up,                
then you can proceed to using   
the fetchedResultsController    
in your tableViewController.    
First thing you have to         
do is perform fetch on          
the fetchedResultsController.   
That will cause it to go out    
and do your NSFetchRequest,     
basically.                      
It's not gonna pull             
all the data over, but          
it's going to basically bring   
over, do the same thing as if   
you had executed                
the fetchRequest yourself, and  
then you're gonna wanna do      
tableView View.reloadData.      
And that's because you want     
all of your datasource          
methods to be called, and you   
know that we've implemented     
all of them in terms of our     
fetch results controller as     
showed on the previous          
slides there.                   
And the only other thing        
you want to remember to do      
is set your fetch results       
controller's delegate to be     
yourself and, again, we use     
that fetch results table view   
controller code that added      
the delegate methods for        
the fetch results controller    
to the UITableView controller   
until we can do all the things  
that is necessary to            
be a fetchedResultsController   
delegate.                       
And what that buys you is       
that anytime in the database    
changes that would affect       
the NSFetchedRequest            
that you wired up to your       
fetchedResultsController.       
Then, it will use that          
delegate to ask the table view  
to update the rows or           
sections,                       
whatever happened to change.    
So let me talk a little bit     
about what's coming up here,    
on Wednesday, I'm gonna do a    
big demo that shows you all of  
this stuff, as usual.           
Assignment five is              
going out on Wednesday,         
it'll be due                    
the next Wednesday.             
It's going to be to add Core    
Data stuff to your Smashtag.    
On Friday,                      
very relevant section.          
It's using CloudKit             
to do a database.               
Okay?                           
Now, Core Data and CloudKit,    
what, what are they,            
how are they related?           
Well, Core Data is for          
doing things that you would do  
with a relational database,     
these powerful queries and      
searches and things like that.  
Cloud Kit is, what if you       
wanted to have a database       
on the network,                 
in the cloud, okay?             
A network that's being shared   
between multiple people or      
even by a single                
person on multiple,             
on multiple of their devices,   
or whatever.                    
So there quite different in     
the way they approach things.   
In Core Data, we do the schema  
using this visual mapper.       
In CloudKit, it's essentially   
schema on the fly.              
As you start saving vars,       
it starts making this           
schema up for you, so           
it's a very different kind      
of way of thinking about.       
You don't think of it from      
a scheme of design point.       
In advance, there's kind of     
more organic as you go and      
also you don't have to,         
you know, kind of create this   
whole scheme of front and       
describe it, you can describe   
it as you use it essentially.   
So it's a very interesting      
comparison between the two.     
I wish I had time               
to do CloudKit.                 
Last quarter,                   
I had the extra lectures.       
I was able to do CloudKit       
as a whole lecture but,         
we'll have to do it as          
a Friday section this week so,  
don't miss that.                
Next Monday is a holiday.       
So no lecture and               
then next Wednesday,            
I'm gonna go over               
your requirements for           
the final project,              
which are required to do.       
And I'm also gonna have a       
lecture as well on AutoLayout.  
We'll finally get               
to Autolayout and               
how do that Autolayout stuff.   
I'd say, I just wanted          
to show you that and            
I will see you                  
all on Wednesday.               
>> For more please visit        
us on Stanford.edu.             
