Tip:
Highlight text to annotate it
X
>> [music] Stanford University
[ Silence ]
>> Welcome to number 13 of Stanford CS1-93B,
the fall of 2013-14, and today, I'm going to go
over the requirements for your final project,
and then I'm going to talk a little more, a few more slides
about Core Data, and how it hooks up with UI TableView,
because those two are a match made in heaven,
and then I'm going to do this gigantic Core Data
with TableViews demo.
Alright, so you're final projects.
There's kind of two phases to your final project;
one is you have to submit a proposal
for us, which we'll review.
We're mostly just reviewing it for scope,
to make sure you haven't picked too big a project
or too small a project.
Okay, we're not, you know, looking in detail
of every single thing you're going to do.
We're just trying to make sure you're headed
in the right direction.
Because over the course of the final project, you're going
to of course talk to us, and ask us questions and interact
with us to kind of get an idea of getting, you know,
hitting a good target at the end.
So, that is really, do immediate.
We'd like you to get us your proposal.
If you know what you're going to do,
please submit a proposal as soon as possible.
If you know what you're going to do,
please submit a proposal as soon as possible.
If you don't get on it right away, and submit it as soon
as possible, really though
by next Wednesday would be the latest we'd want
to hear from you.
And, I hate to say that, because I know a lot of you wait
until the day before deadline to do anything, and I understand
that impulse, but this is something where you want to get
that proposal in sooner, in case we have issues,
and we can get back to you, and you either write,
maybe come up with a whole new proposal if what you're thinking
about is just not going to work.
Then the second phase is the final project itself,
and that project, the code for the project,
along with the keynote, set of keynote slides
for a two minute presentation about your project are due
on Friday, December 6, okay?
So, that seems like that's far away, I know,
that's over a month away, right.
It's November 6 right now, but you got Thanksgiving in there,
so it's really not that far away, and so your final project,
like a final project in your class,
where you get multiple weeks to do it, you do not want to wait
to the last week to get started.
So, get started immediately.
You have everything you need now
to start building an application.
Yeah, no late days on the final project at all.
Simply will not accept it late.
Whatever you have on December 6 at midnight, submit it.
I don't care what it is; submit it, because that's all.
I'm not going to accept anything.
I just can't, because I've got a lot of students
who are taking this for a grade especially, and that's a lot
of time I have to be fair to those people, and also,
I have to get started grading immediately.
The presentation that you're going to do, two minutes,
it's really just going to be pitching your project to us,
to your fellow classmates.
If you can imagine, it's like you're trying to pitch a VC
to invest in your company or to do the app,
or you're just trying to get people to buy it, or whatever.
It's that kind of presentation.
I'll leave it up to you.
You can certainly do a live demo if you want.
You'll need iPhone 4S or later, or you'll need an iPad 2
or later, in order to hook
up to this wonder projection system we have using Apple
TV mirroring.
But, you don't have to do a live demo.
Live demos are perilous, as you can see, what I do each lecture,
but they also kind of can be effective, and a really good way
to show off your app, so it's kind of up to you.
And, that presentation is required.
I will have an alternate presentation,
which is the last lecture of the quarter,
which is the week before the final exam period.
So, that's that.
Yeah, the scope is basically three weeks
of homework worth of work.
You should know by now approximately what that is.
Remember in the past when the people have
to pass both the homework section
and the final project separately.
You can't bomb one, and get an A
on the other, and pass this class.
Your final project has to work on hardware.
You have to show it working, either in a demo
in your two minutes, or if you don't show a live demo
in your two minutes, you have to show your TA.
Only iOS-SD code counts, so if your app has a backend,
some server somewhere, you get no credit
for any of that really.
You're only getting credit for iOS code, okay.
So, simulate your backend if you have to,
or if you have the backend from somewhere else, that's fine,
but don't waste time doing non-iOS code
in this three weeks, because you're not going
to get any credit for that work.
And, you'll be graded on your proper use of the SDK,
and also proper object-oriented programming,
and your aesthetics will matter.
So, don't put a big junky-looking UI that just like,
really looks terrible, and yeah,
don't get sidetracked on non-iOS code.
That's kind of a repeat of all that slide there, so.
The presentation quality matters a tiny bit.
It does matter.
Giving your presentation,
effective presentation is a very important skill to have.
All of you at Stanford should be good at that by the time you get
out of here, so here's just another chance
to really practice doing a good presentation.
Time it; see how long it's going to take.
You know, run through it a couple times practicing.
You proposal needs to have sections in it.
Okay, the first section is kind of an overall description.
What am I doing?
This is best shown by example, so I have this example here,
which is a Shakespeare Director App,
so let's say you're a director at a theater company,
and you're going to be direction some Shakespeare plays,
and this is an app to help you do that.
And so, it has a way to bring up a Shakespeare play
from the folio database, and then you can lay
out the blocking, which is like where the scene is set up,
where the people are standing and all that stuff
of each scene, lined up with the dialogue.
And then, it's also got a dialogue learning mode
for people who want to learn the dialogue, learn their lines.
It will say the other parts, and then you can say your own part.
So, you can see that this is kind of a description
of what it does, as opposed to how you're going to do it.
Section 2 is what parts of iOS are you going
to use to implement it.
Okay, it's going to have TableView with custom cells.
It's going to use the camera.
It's going; you know text fields with in popovers.
It's going to use AV foundation.
It's going to NS Timer.
It's going to have Core Data,
and where there are going to be my entities.
It's going to print out the blocking things to printer,
which is something we don't cover in class.
And, you're required to have one feature, at least,
that it was not covered in lecture.
Okay, and so that task is on there; not only so you have
to learn something from a documentation,
instead of my kind of getting you started with it,
but also so that you peruse all of iOS
and find out what's in there.
So, don't come to me and say, oh, can you tell me a feature
to do for non-iOS not covered in lecture?
It's like, that's part of the task for you to go figure
out what's out there and pick something.
Okay. So, that's what your proposal needs
to have, these two sections.
What it is you're opting to do,
and then what iOS apage you're going to use that you know
of right now to implement.
Okay? And, here's some notes, again, you're going
to review these slides offline to really get a good feel
for what makes a good proposal, and you can ask on Piazza
for clarifications, etc. Okay, so, the next topic I want
to talk about is Core Data still,
but its Core Data and TableView.
How Core Data and TableView go together.
Because Core Data is a bunch of, you know, objects,
a big object graph, and TableViews are really good
for traversing through object graphs, okay?
So, how do we do this?
There's a great class
in iOS called NSFetched Results Controller.
This class' only purpose in life is to link an NSFetchRequest,
which hopefully you'll remember
from two days' ago lecture with a UI TableView.
That's what it does,
it basically bonds those two things together,
so that the Fetch; anything
that Fetch would be fetching is always showing in the TableView,
even if the database is changing underneath that FetchRequest.
Okay, it's still going to be updating the TableView.
So, the way this works, it's really two parts
for the Fetched Results Controller.
One is it answers all the questions
in the UI-TableView data source protocol,
like how many sections, how many rows and sections,
and even some ones that you don't know about,
some more advanced ones.
It answers those questions as well.
So, it's able to answer all those questions,
using code kind of like that.
Also, it can tell you at any given time,
what thing in your database,
what entity in your database is being shown
in a given row, okay?
There's a one to one mapping between a row in the table
and some object in the database.
Alright, of course we know when you do a FetchRequest,
it can only return objects
of a certain kind; an array of objects.
And so, this will let you get it.
And, it's a very important method to understand,
which is object to the index path.
Okay, you send that to the Fetched Results Controller,
and it will return you a photo star,
or a photograph photographer star
or some NS Managed ObjectStar, which is the object that's
at that row, and then you can pull out the attributes,
and put them in to your UI-TableView cell
in self row index path.
Okay? It's really important to understand that method.
How to you create one of these NS Fetched Results Controller.
Okay, its Allocinit looks like this.
It takes a FetchRequest, a context.
That's obvious where we're going to be doing the fetching.
Right? It will even do section headers, so you specify
which attribute in the objects that your the section,
the name of the section,
and then it will divide the table into sections.
And, it can also do caching, okay, so we'll talk
about those last two things in a minute here.
But, let's take a look at what kind
of FetchRequest we might create to put
into a Fetched Requests Controller,
so here I'm creating a photo request, so I'm going
to be fetching photos.
I need a sort descriptor
that says what order these photos are going to be
in in the TableView, so I'll sort them
by their table, let's say.
And, then a predicate.
I'm going to get all the predicates that were taken,
all the photos rather that were taken by a photographer
with a given name, photog name.
Okay, so I just specify the predicate.
So, you I just basically create a normal NS FetchRequest,
and then I just do this fetch results controller alec,
FetchRequest context, section key name and cache.
It's as simple as that, okay?
Now, oh, yeah, so, those last two items.
The cache by way, one thing about the cache,
if you specify nil, it won't cache.
Caching means that it will cache the results of that fetch
between launching of your app.
In other words, it will permanently,
you know, on disc, cache it.
This is not caching it member.
You know, it's always going to do it in memory caching.
Core Data does that.
So, this will make so between launches,
it has this result cached, but if you set that to non-Nil,
okay, you better keep your FetchRequest exactly the same.
If you change anything about your FetchRequest, and come back
and try to use your cache, it's going to fail.
So, this is only really for TableViews
that have the same Fetch Request all the time,
exact same predicates or descriptors.
Everything's the same.
If you're going to use that section key thing,
try and put sections in your table, the sort descriptors have
to match up with the section keys.
In other words, the rows in the table,
the photos that you fetch, have to be in the exact same order
that section headers would be,
and this is a normal TableView thing, right?
The section headers always have to be
in the same order as the rows.
Well, that's true here too.
So, almost always, your first sort descriptor will be the
section key header, to make sure everything is sorting
in the same order.
The Fetched Results Controller also has a delegate,
and using that delegate, it can watch what's happening
in Core Data, and when something changes
that would affect your FetchRequest,
it will change your table, which is incredibly cool.
Okay, that means if you added a photo,
and if it would have matched your FetchRequest,
it will add a row to the table, and you don't have
to do anything, because it's watching.
It's using that NS Object Managed Context,
objects did change radio station, it's listening to that,
and it's changing it with methods like this, okay?
So, there's really two things
to get a Fetched Request Controller hooked
up to your table.
One is, you've got to use it
to implement all those UI-TableView data source things,
and two, is you've got to set its delegate,
and then use all these methods to have it watch,
but we've made that easy for you.
I've created a class called Core Data TableView Controller,
and I'm going to make it available to you.
All it does it those two things, and you're welcome to look
at the implementation of it.
It's all pretty much just one liners
that are just using the Fetched Results Controller
to implement the data source,
and to do the delegate business, okay?
And, the only thing you need to know
to use Core Data TableView Controller,
it has a property called Fetch Results Controller
and you just set that to a Fetch Results Controller,
and it will just work.
Nothing else required to do.
You just set that, and Core Data TableView Controlled will then
use it to answer all those data source questions,
and also it will set the delegates
of the Fetched Results Controller,
and make it so it watches the database properly.
Okay? So, that will be included in your homework.
You will definitely want that for your homework.
I will be using that in the demo today.
Alright, so speaking of the demo.
This is a huge demo.
I may not get all the way through it.
It covers some things that I haven't covered in lecture yet,
and that's kind of intentionally.
This is the only lecture I really do that,
but I just wanted to kind of show you some things
that I didn't really want to spend lecture time on.
I might come back to these in future lecture, but anyway,
there's a lot, lot there to cover,
and you have these slides in front of you.
Hopefully you can see what the list there is.
I'm not going to back to the slide, so coming up;
today's your last homework.
We have an instrument, which is performance monitoring adjunct
to X code on Friday's section, and then next week,
we're going to talk a little bit about multitasking.
I say more multitasking, because I'm going to do some of that
in the demo today, and then we're going
to do some more advancing Segway.
So far the only Segwaying we've done is,
UI-Navigation Controller pushed Segways basically,
and then also, we talked a little bit
about iPad replace Segways,
where you replace the entire detail view,
which is kind of a weird Segway.
We're going to talk about some more kinds of Segways
that we can do as well.
And, maybe we'll get to Mapkit next week
or maybe the week after.
Okay? Alright, any questions before I dive
into this monster demo?
Okay, feel free to stop me.
A lot of time when I'm demo, I'm typing away,
I'm not seeing you raise your hand, so feel free to shout out.
So, I'm going to create a new project here, and I'm going
to do single view application, even though I'm going
to use Core Data, and I told you that if you click on this one,
you can see some generated Core Data code.
I'm actually going to use the code that's generated here,
but I put it off into a category of my application delegates,
so that you don't really need to look at it.
I'll include it in the demo, and you can see it.
But, for your homework, you're going
to do your Core Data stuff using a documented.
UI-managed documented, and I'm not going to show that.
Because I want you to kind of go through the process of trying
to figure that out for yourself.
So, I'm just going to create our normal view single view
application like we usually do.
I'm going to call is Photo Mania, and it's going
to be universal app, although I'm only going
to use the iPhone version.
I'm only going to do the bare bones of this application.
What this application is going to do, it's just going
to query Flickr those URL,
the URL for recent geo reference photo theme,
the same thing we did for Shutterbug.
But instead of just showing the photos,
it's going to show you the list of photographers
who took those photos.
And then, you know, after this demo, you could easily make it
so if you click on a photographer,
it shows you the photos by that photographer.
Click on the photo; use the image view controller
to show you an image.
So, that's kind
of the application we're trying to build.
We won't get all the way to building those other TableViews.
We're just going to do this main TableView,
but that's what this is going to do.
And, the way it's going to do that; the way it's going
to show those photographers is kind
of a little bit different strategy
than we saw with Shutterbug.
I'm going, in the background, basically of my application,
be constantly querying Flickr every once in awhile,
and getting more and more photos,
and then just throwing them into a Core Data database.
Okay, just throwing them in there in the background.
Meanwhile, I'm going to have TableViews that are going
to be looking at that data.
Looking at the photographers, clicking on them,
looking at them, looking at the photos, and that's just going
to be always be updating automatically, all the time.
Okay, so that's the app that we're going to build.
So, there's some things to talk about here.
How to build a Core Data database.
How to hook it up to a TableView
with the Fetched Results Controller.
How to fetch things in the background.
Okay? We're going to talk
about all those things today if we have time.
Alright, I'm going to call this Photo Mania.
I'm put it the developer where I usually put things.
Here it is.
I'm going to dive right in with building my data model.
My schema, as you would call it in the database world.
This is a description of all the entities and all that stuff.
We saw how to do this all in the slide, so I'm going
to just going to show you what it looks like live.
So, when I want to create a new schema, I do new file.
Okay, so I'm going to do new file.
I'm going to go up here to Core Data, and pick this data model,
not mapping model, data model right here, so click that.
We can call it anything you want.
I'm going to call this one the name of my app, photo mania,
and it's asking where do you want to put it, and I'm going
to put it at the top level here
where all the rest of my stuff is.
Here's my controller and delegates something like that,
so I'll put this data modeling file there.
And, so it creates this data modeling file.
You can see it's empty.
I've no entities or attributes or Fetch Properties
or any of that business.
So, let's just start adding some.
So, I'm going to go down here to the bottom, add entity.
Click that.
It added one, called entity.
I'm going to double click, and call it photo.
So, I need photo, and I display photographers too,
so I better add photographer.
Now one thing that's really important
when you make a schema is you want to put the entities
and the attributes in there that support the kind
of UI you're building.
Okay, and that's really important for you
to understand in your homework.
Okay, this homework that I'm assigning you is pretty
straightforward, as long as you pick a good schema.
If you pick the right entities and attributes in the database,
it's just really easy to just throw up tables of information.
If you don't, if you have kind of the wrong schema
or just too simplistic of a schema, you don't put
in a couple of attributes that you need to make your UI work,
it can be like ah, how do I get that information.
So, the schema is your slave,
you get to make the schema however, you think it's going
to best support the application that you're building, okay?
So, photo and photographer.
What kind of attributes does a photo have?
Well, let's see, of course it has its title,
and it has a subtitle.
That's that little description from Flickr.
It has the URL of its image from Flickr.
Probably has the URL of its thumbnail as well.
In fact, we could even store the thumbnail data,
which you're going to want to in your homework, right in here,
put the data in, not just the URLs, and also importantly,
photos have a unique identifier that comes from Flickr.
Because when I get data from Flickr, I don't want to be,
sometimes you click Flickr, you get the same photo again,
and I don't want to be duplicating
that in my Core Data database.
So, I'm going to look at that unique ID from Flickr,
and make those unique in my Core Data database as well.
So, I've added these, but I've got to set their,
you can tab warning here, or any error,
because I haven't set these.
If I click on this, you'll see.
Must have a defined type, so we got to set a type for these.
These all happen to be strings; all four of these,
but you could image putting things like dates,
like for your recent tab in your homework.
You probably want to have some sort of last viewed date
or something like that.
That's perfectly reasonable to put in here,
and numbers and all that stuff.
So, we'll just do that.
Photographers are a little simpler.
They just have a name.
Okay, a photographer has a name.
That's a string.
That's about it.
And, remember I told you we could look
at these entities graphically
with this little button down here.
Here it is right here.
They're kind of smashed on top of each other,
but I can pick them up and move them.
And, you can see that as I move one, it kind of makes space,
alright, keep them, and if I have relationships between them,
it will keep those relationships sensible as I move them around.
So, let's create a relationship.
What is the relationship between a photo and photographer?
As we saw on the slides, who took, basically,
so I'm just control dragging.
I'm holding down control right now, and dragging from photo
to photographer, and I have this new relationship created.
And again, if I move these things around,
this things will stay with, so let's go ahead
and give these relationships names.
On the photo side, this is the who took relationship,
and on the photographer side, this is the photos,
and we can inspect this right here
with this little guy right here; the inspector.
And, we can see all kinds of things
about our particular properties.
This is true for properties, and also for relationships.
And, of course, we know
that this is a too many relationship, right?
Because a photographer can have many photos,
so we get this double arrow here.
But, it's a two one relationship here, because a photo,
only one guy took the photo.
And so, if you move these things around,
it will keep this all kind of looking okay.
Alright? So, now, we've kind of set
up everything here that we need.
This is a pretty simple application,
so we don't need any more attributes.
But, in your application, you're going to have at least one
or more two more entities and some attributes on there,
and some more attributes on photo.
So, I left with some work to do.
Okay, so now that we have this, we want to be able
to access all this stuff
in our objective C code using properties
and normal class syntax.
So, we're going to do this thing we talked about,
which is generating manage object subclasses.
So, I'm going to pick the classes that I want.
I'm going to go here and say create NS managed objects
subclass for photo mania, and we'll do photo
and photographer, both of them.
And, we click this, says where do you want them?
I'll put those also at the top.
I'm going to put everything at the top level here.
And here, I have my photo and photographer, and I can see
that photo looks okay.
It's got photographer who took,
but photographer, not so much, right?
It's got NS manage object for remove photos object.
This should really be photo star, so I'm just going
to generate these things again.
Okay. And really, it's too bad
that it doesn't automatically do this two pass generation,
but you end up doing it yourself.
Get used to doing this generate,
because you're going to do it a lot.
You're going to be constantly adding entities,
changing attributes, like that, and you're just going
to constantly be regenerating these things, and it's going
to ask you to replace them, and so don't be uncomfortable
about doing that regenerate.
It's a common thing to want to do,
and so now we're winning here.
Okay, so we have these nice classes,
and now we can use properties to access all their attitudes.
My photo dot title to get at the title for example.
But, as I said before, we might want to add code, and I do want
to add code to photo here.
I want to add code to create a photo.
Okay. To make so that I can add,
insert a photo object into the database.
And so, I'm going to do that using categories.
Remember categories is that new objective C thing I was telling
you about, where we can add code to a class
without sub-classing it, so I'm going to add code
to this photo class, right here, without sub-classing photo.
Okay, so I do that with file, new file,
and instead of picking objective C class,
I'm going to pick objective C category.
And when I do, it's going to say, what class do you want
to make a category on, I'm going to make a category
on the class photo, and I'm going to call it Flickr
because that's what this method that I'm,
these methods I'm going to add to photo are all kind
of hooking Flickr up to the database, so Flickr seems
like a good name for that category.
And, it wants to know where I'm going to put them.
Put them in the same places everywhere as everything,
and so here's my .H and here's my .M,
and it's asking me what do you want to do here.
So, the method that I want to implement here is a method
that essentially takes a Flickr dictionary
and adds a photo object to the database,
and returns the pointer to it to me.
Everyone understand what I'm going to do here?
So, I'm going to call this thing, photo,
make sure I pick the same name,
so that I don't get sidetracked here.
Photo with Flickr info and this is going be NS Dictionary,
photo dictionary, and what else do I need beside
that photo dictionary to create an object in the database?
A hook to the database.
Okay, I got to know which database you want me
to add this photo too.
So, I also need in managed object context,
NS managed object managed context context.
Okay, and that's all I need;
just the Flickr information and the context.
That's the place you want me
to create this photo, and I will, okay?
And, I'm also going to have another one here; because I know
that I'm going to be downloading these Flickr photos
in big bunches.
Every time I call URL, geo reference photos
or whatever it's called, I'm going to get a whole bunch
of them, like a hundred or 200 of them.
So, I'm going to have a bulk load one that I'm going
to call load photos from Flickr array, NS-Array photos
of Flickr NS dictionary into managed object context.
Whoops, NS managed object context context.
Okay, so that's just going to bulk.
It's going to call this basically repeatedly,
although that might not be the most efficient way to do that,
and we'll talk about that in a little bit.
So, let me implement these two methods.
Okay, this is the interface of my category,
and so here's the implementation of my category.
Now, I can do whatever I want to implement these, except,
I can't use any instance variables,
so I can't have any properties that are, you know, here,
so I have to implement them basically in terms of photo,
if that makes sense that way.
So, this is going to return a photo, so I'm going to say,
photo equal nil, and down here, return photo, and in between,
I got to go find this photo in the database, or create it,
or whatever it may be.
So, let's start with asking the database,
do you already have this photo?
And, so how am I going to ask the database
if the photo is already there, and the answer is,
I'm going to try and fetch it.
So, I'm going to have a Fetch Request, and it's going
to be a Fetch Request into the photo table,
if you know anything about it, or into photos.
It's going to return photos, okay,
because I'm trying to find this photo.
And then, the request needs a predicate,
and what is the predicate.
Which photo am I looking for?
Well, I'm looking for the photo whose unique equals the same
unique that is photo dictionary right here,
so let's go get that.
NS-string star unique equals, and we're going
to need our Flickr Fetcher import, Flickr Fetcher .H,
so I'm going to grab Flickr Fetcher .H
from the thing we did before, which was Shutterbug.
So, here's Shutterbug, and here's Flickr Fetcher.
I'm just going to dray that whole thing right in here.
Alright, so now I have Flickr Fetcher .H,
and inside Flickr Fletcher .H, we can get the photos unique ID
with this Flickr photo ID.
Okay? So, I'm going to go down here and say,
photo dictionary, Flickr photo ID.
Now, I might want to do value for key path here,
just in case this Flickr photo ID might have dots
in it or whatever, Flickr.
You know, it might have dots in it like the description has.
Okay, I'll leave it this way here,
but value for key might be a good idea.
So, I'm basically going to fetch into the database to try
and find this unique photo; see if it's already there.
And, I do that by saying I need an NS error here,
and then I'm going to say NS array matches equals context,
because we always have to ask a context to do a fetch.
Okay? Execute Fetch Request, that request,
and if there's an error, return an error.
Okay? So, now I've got those photos.
Those photos hopefully, in this case a matching photo
or maybe not, has been pulled out.
Now, this matches can have a number
of different states or different values.
One thing is, it might be nil.
If it's nil, okay, or if this error is not nil, let's say
or error or another error condition here is
that the matches, matches count is greater than one.
Okay, because these are supposed to be unique,
and so if I somehow got multiple photos by doing this,
that would also be an error condition,
so I have to handle error here.
Handle error.
I'm not going to do that today, but you can imagine.
Okay, otherwise, if the matches found something,
then we can just return it, okay?
So, how do we return it?
This is in array, but this array is going to have the one
and only one match, so I'm going to say matches first object.
Could also say last object.
Otherwise, this matches dot count is 0,
so it returned an array, an empty array.
That means I looked for that photo that had that unique,
I couldn't find it, so that photo doesn't exist.
I now need to create it.
Okay, everyone remember how
to create an object in the database?
NS entity description, insert new object for entity for name,
we're inserting a photo, and we obviously have
to specify the context.
Okay? So, we created a photo.
Excellent.
And, now, let's go ahead and set the attributes of the photo.
I'm also going to set the photo's unique, go to unique.
Alright, so here I'm setting the photos title,
subtitle, image URL.
So here I'm just setting the title using value for key path
out of the Flickr dictionary, the subtitle,
given the description, the URL.
I'm using this URL for photo format thing.
I have to turn it into a string, okay, because can't URLs
in the database, but we can put strings there,
and then I also have the photographer name,
but I have a relationship to photographer entity,
so now I need to create a photographer as well.
So here, loading a photo, right from Flickr,
is causing a photographer also to be created.
Okay, and this is happen in your homework too in spades.
Okay, where you're going to download these photos
from Flickr, and you're going to build your entire database.
Lots of entities are going to be created all the time,
every time things come back from Flickr, okay?
So, how do we create a photographer?
Well, I'm going to do the same thing I did here,
where I have this photo category that creates that,
I'm going to do the same thing for photographers.
I'm going to say new file, another category.
This is going to be a category in photography, photographer.
This one's not Flickr specific,
because photographer only has a name, so I'm going
to call this category, just to be different,
create, instead of Flickr.
Okay? So, we'll put this in the same place.
Here it is right here.
Put this up here, and Photographer, yeah.
It's very similar.
It looks almost exactly the same.
We're going to fetch for it.
We'll handle, if we can't find it,
set the name, all that business.
So, we put that in the other file, okay.
Just trying to speed it up a little bit here.
You wouldn't learn anything new by my doing this all again.
Okay? But, now I have a way to create a photographer,
given a name in a given context.
So, we'll use that over here,
and we'll just say photo.whotook equals, and we've got
to import that little category.
Photographer create.
Photographer, oops, photographer with name
and the name is the photographer name that we got
out of the Flickr thing, and same context.
Okay? Everyone understand this method right here.
So, this method is going to, if we give it a Flickr dictionary
from photo info, it's going to give us back a photo object
in the database, either by creating it
or by finding one that's already there, and it will return nil
if it has a problem with it.
Everybody got that.
Okay. So, now that we have this thing,
we have these nice ways to access it.
Let's talk a little bit about the TableView,
and how we're going to display this stuff in a TableView,
and it's really a simple matter
of creating a new TableView subclass that implements
that Fetch Results Controller business.
And I told you that you were going
to have this Core Data thing to make that easy,
so we're going to use that.
Here is the Core Data TableView controller.
We'll drag it in.
We'll take a look at it here.
Alright, so here's the Core Data TableView.
Here's its header file.
You can see, it just has this Fetch Results Controller thing.
It also has a way to force it to Fetch,
but you don't ever have to do that.
It will happen automatically.
So, it has this property, and if you look
at this implementation of this thing.
Besides setting the Fetcher Results Controller,
which is mostly just a bunch of logs, okay, that I put in there.
It's implementing UI-TableView data source, you see,
in terms of the Fetch Result Controller.
And then, it's also doing this delegate business,
where it's watching for changes in the database.
Okay, and that's it.
That's all it does.
And this code is actually copied and pasted
from the documentation for NS Fetch Results Controller,
so this is nothing exciting in here.
So, when we create a TableView that wants to look
in the database, okay, we've created objectives in face,
we're going to make it be a subclass
of Core Data TableView Controller.
So, I'm going to create one, and I'm going
to call it photographers, I'm going to call it CDTVC,
Core Data TableView Controller.
Okay, it's kind of a naming convention some people
like to use, and so I'm going to do that.
Because it displays photographer;
that's what it does.
So, let's create that.
Let's put it top level; same place as everywhere else.
Here it is.
It's created it.
I don't need any of this business for that.
And, let's think about its public API.
What does this thing need?
Well, it needs what most things need
that are doing database stuff.
It needs an NS managed object context, and so, this class,
its job in life is going to be,
it will show you all the photographers
in a given context, the given database.
You give it a point or two databases; it will look in there
and show you all the photographers in it.
That's what this thing is going to do, okay?
So, to make that happen, all it needs to do is set
that Fetch Results Controller thing in its super class, right?
Which is its Core Data TableView controller,
so I'm going to do that.
As soon as someone sets the managed object context.
Let's call this managed object context,
so it's a little clearer.
As soon as someone sets this managed object context,
I'm going to be able to set up my Fetch Results Controller.
I can't set up my Fetch Results Controller
until I have the context.
Sometimes, the context comes to me via public API like this.
Some view controllers will get their context
from other objects.
Most notably, and pay attention here for your homework,
if someone gives you a managed object like a photo
or a photographer, you now have the context,
because NS managed object has a method
in it called managed object context.
It will give you the context
that that object came out of, okay?
So, it's really important to understand.
If someone gives you a photo,
you have a managed object context,
but this thing is at the top level.
It's showing all the photographers.
We don't have anything yet out of the database, so someone has
to tell us the context.
Which database to fetch these things out of?
So, now I just need to say,
Fetch Results Controller equals something, and so I'm going
to create a new Fetch Results Controller.
Alec in it, and it's in it has all these arguments here.
It needs a Fetch Request, okay.
Actually, let's, so we don't get this kind of blackiness,
let's go ahead and make all the arguments first.
It needs a Fetch Request,
because that's what it does is hook up a Fetch Request
to something, and so, this is a request
into the photographer table, right, so we want photographer.
We're going to show all the photographers.
The predicate for this thing is nil.
What does that mean predicate nil?
Predicate nil means all of them.
Okay? So, if you say predicate nil,
that means give me all the photographers.
And sort descriptor, yea, let's sort these things.
Let's sort them by, let's see, sort descriptor with key, well,
let's sort photographers by their name.
Okay? Amazingly, you can actually sort things by things
through relationships.
So, you can sort it be other objects properties if you want.
But here, photographer, we're going to have it sort
by its name, and yes, we're going to have it descending,
and we're going to use the selector here called localized
standard compare, okay.
Which is what we use mostly for stings that are going to appear
when these interface, okay.
We need to close our array there,
because this is an array of sort descriptors.
We only need one, and we could limit like,
for example we could say, only give us a hundred.
We only want to see a hundred photographers,
which would be kind of silly
because we are sorting alphabetically,
so this would not make sense, because we wouldn't get
to see the people whose names unfortunately happen to be end
of the alphabet, but we wouldn't do it here.
But, in other cases you would.
In your homework, you very well might do that.
Alright, so now, we have the request,
we have the managed object context.
That's an argument to this method is what we're
setting actually.
Here's the section thing.
We could make sections here, but there's really nothing
in a photographer to do that, so we won't do that,
and we're not going to catch, okay?
So, that's it.
That's really all that's required
to make this TableView work, except for one thing,
which is that Fetch Results Controller,
I told you it implemented all the UI-TableView data source
things, but there's one of them it can't implement
which is self row and index path.
Okay, it doesn't really know what attributes
of the object you want to put in which parts
of the UI-TableView cell.
Right? The title, the subtitle, it doesn't know those things.
So, we have to implement that ourselves.
So, that's UI-TableView cell, self erode index path.
You should be very, very, very familiar with this thing.
It just looks like this, cell equal, self.tableview DQ,
and well, these are photographers,
so we'll call this photographer cells.
We got to make sure you guys are going to keep me honest.
Make sure I remember to set that in the story board
when we create one of these in the story board.
And now, I need the photographer that is at this row and section.
So, I'm going to import photographer first of all,
not create, .H. Okay, so there's the photographer.
And, then I'm going to say photographer equals,
and how do I do this, photographer equals self.
Fetch results controller, objected index path, index path.
Now I have the photographer that's in this row, okay?
So, now that I have that, I can do things
like text label.text equals let's say the photographers name
of course.
Also, how about something cool like this,
cell.detail text label equals a string with format.
What if I wanted to put how many photos this photographer has
taken, well that information is readily available to me
in the database, percent D photos,
photographer.photos count.
Okay, X code, shoot, the way it does that.
Okay. Right.
So, I just go through that thing that goes through that thing
that who took photos relationship.
I just grab the photos side.
It's an NS set.
NS set implements count.
I got what I need, okay?
And, then let's return this cell.
Okay, every one understand this self erode index map.
Question?
>> Fetch Controller came in from Core Data table controller
that was subclass?
>> Yes, this property spectral controller is inherited
from Core Data TableView.
That's actually a good question.
Okay, so let's go ahead
and build our story board while we're at this,
and while we have this fresh in our minds.
So, here it is.
This is the kind of default one that we got.
Let's get rid this.
We don't want this.
Let's go bring out a TableView.
So, here I'm just going to drag a TableView out here.
I'm going to set it to be a photographers Core Data
TableView Controller, right, and then let's set
up our cell the way we want.
We want it to be subtitled, because it's going
to have the photographer name
and then how many photos they took.
We need to make sure that its photographer cell is our
reuse identifier.
Otherwise, we're ready to go.
So, if we had stuff in our database,
and we hit run right now, this would work.
That's all we needed to do.
An incredibly small amount of code to hook
up a table view to Core Data.
But, of course, we have no data in our databases.
Nowhere in our code are we querying from Flickr
or loading stuff in, and so I'm going to use the opportunity
of our needing that to introduce you for the first time
to your application delegate.
So, I've always been moving down to supporting files.
Don't look at them, you know,
and show now I'm going show you a little bit what's in here.
So, your application delegate is kind of like,
it is watching what's going
on at the highest level of your application.
It sees your application has launched.
Okay. It sees that your application has resigned being
the active application.
It sees that your application is entering the background.
Okay, we know then iOS, the apps,
when you go to another app, they don't quit, they just kind
of move into this background state,
right, so we can find that.
You can find it when you move back into the foreground.
If you become the active application.
If someone's quitting your application,
you find that out as well.
So, it finds out all these things, and we're going to learn
about those later in the quarter, so I'm going
to delete all those now, but we are going to look at this one.
This one is did finish launching with option,
so here it's tell you your application finished launching.
Okay? This is a great time to do things
like kick off some Flickr fetching or something.
Now, if I'm going to be doing my Flickr fetching here
in my application delegate, I need the context.
Okay, now in your homework, you're going to do
that by creating a UI managed documented.
But, here, I have a little piece of code that I got
from that other template that I was telling you
about that I'm going to bring in here.
It looks like this.
It's a little category, and it has this method,
create main cue managed object context.
So, that's a managed object context that attaches
to a database, the database for this app.
This only has one luckily, and gives me; it's on the main cue,
just like a UI document one is, so this code can be similar.
And then also, I can save it.
Now, I don't need this save context message for you
on managed document, because it auto saves.
But, here if I create this manage object context not using
a document, then I have to do that.
So, this is, like I said, the other way to do it,
which you're not going to do for your homework, but I just wanted
to show you, I didn't really didn't want
to show you the UI managed document, because I wanted you
to figure that out on your own,
so we're going to manage this one.
Okay, so I've added this.
This is a, you can see that the photo mania app delegate
category, so it simply added these two methods
to my app delegate, okay?
No, what I'm going to do here is I am just going to,
first of all, let me create some property.
So, this is some stuff that I just created, some properties
that I need and stuff like that.
For time, I'm just going to put them in here,
but as we use them, I will refer to them.
But one of them I'm going
to use right here is this photo database context.
So, I'm going to keep a property in my app delegate,
which is the context that we're going to be fetching into
and that we're going to be reading out of.
So, I'm going to set that right here,
photo data with context equals self create, oops,
got to import that, import photo mania MOC.
I'm just importing the category header file that has that create
in that, so create main cue managed object context.
So, again, you're going to set this as well, but you're going
to set it from your UI managed document.
So, now, I have a context,
and I want to start doing some Flickr Fetches, so I'm going
to call another method here, start, what did I call this,
star Flickr fetch, I think, okay?
So, that's just going to fire off a Flickr fetch
as soon as we launch.
Okay, we just launched.
Get this message gets set to us when we launch,
and I'm just going to fire off a Flickr fetch.
So, that's one of the times we're going
to fetch is as soon as we launch.
We're going to fetch some other times, so we're going
to fetch as soon as we launch.
So, I'm going to go ahead and put this in here
so we can look it, instead of my typing it in line by line,
and this is something where it's got some stuff
that I didn't teach really in detail in lecture,
but you should mostly be able to understand.
Mostly what this is doing here is it creates a session,
so you know about URL sessions, so I'm creating this session.
This session is a little different
than the one we created before, because look, it has a delegate.
You see that.
We didn't specify a delegate before.
Okay, we had delegate nil.
And, why do we want a delegate, and why are we making it so.
Well, that's because we want these Flickr Fetchers
that we're starting off in the background.
If they finish while our application is no longer
running, we want it to launch our application and tell us.
Or, if we're in the background,
we're not the application the user is using right now,
and this URL Flickr comes back with some information,
we want it to you know, make us, wake us up a little bit
and let us process it.
Okay, so by doing this delegate,
along with a background session, we can do that.
So, I'm going to show you this delegate implementation.
So, I create this session, and then I'm doing here
on start Flickr Fetch is creating a task and resuming it.
So, this is the exact same thing that we did before, right?
We had a URL session.
We created a download task.
The only difference is last time we did with completion handler,
and we had a little block that would happen
when the download came back.
Now instead, our delegate's going to get called
when the URL gets loaded and comes back.
Does everyone understand the difference
between what we did before and what we're doing here?
Okay, no completion handler.
Here, we're going to use a delegate.
So, let's look at what that delegate looks like.
It looks like this.
Okay, there are three methods in it.
These three methods right here.
One is your file just finished downloading, and here it is
as a local file, so this looks a lot
like that completion handler, and then, here's a couple
that we're not going to use, like giving you,
this gives you some progress, how many bytes its read so far,
if it does it in chunks, and this also,
download sessions can get interrupted and then resumed.
We're definitely not going to talk about that, but anyway.
Now, you can see I have an error here, okay, so what do we do.
So, this is what we would have done in our completion handler.
And, all we're going to do here is we are going
to get the context, our little photo database context
that we set up there
and application did finish launching.
We are going to download those photos from Flickr,
so Flickr photos is this, which you're very used to, right?
Data with contents of URL, Jasson, de-Jassonize it,
grab the results out of that.
Okay. So, we're going to do that little thing.
This needs to be happening, you know, this is a local URL,
so it can be happening on the main thread, no problem.
Now, we're going to do something in this context,
and notice I'm doing perform block.
I didn't do perform block over in the photo creating one,
because it's kind of implicit.
I'm creating a photo.
Of course, I'm doing it on that context, so whoever calls
that would want to do that in perform block, and that's,
in fact, what I'm doing here.
I'm calling that method we just wrote,
load photos with Flickr data, okay.
We didn't actually write that method, so let's look at that.
So, that's over here.
Okay, we have photo with Flickr info,
and here's loading the photos.
So, how do we load the photos?
I'm just going to say, 4NS dictionary photo in photos,
okay, so give me each Flickr photo one by one,
and then self photo with Flickr info,
photo in manage context, context.
Now, this turns out to be really an inefficient way
of loading those hundred Flickr photos,
because every time I call this, I am doing this Fetch.
So, if I want to load a hundred photos,
I got to do a hundred fetches to see if those are unique.
Okay, there are much better ways to do this,
and one of your extra credit items is for you to try
and figure out a better way to do this.
Okay, and one way is to look at the unique ID's
of all hundred photos, fetch them all at once,
and see which ones are in the database,
because you can get a list of them back, right?
The ones that are in there, and then one by one, you can go
and create the ones that aren't there.
Okay, so that's one way to do it.
Okay, but this cheap and simple way is good for a demo, okay.
So, back to our app delegate
and now we have this load photos with Flickr array.
Let's go ahead and import that header file, which I do, oh,
maybe I called it something different there.
What's the problem?
Let's see, yeah, I probably called it something different.
Call it the same thing.
Here's my delegate, here it is.
There we close, I called it [inaudible] Flickr, right?
So, that's going to load all these photos.
Notice, I'm saving my context here.
Okay this is a method, manage object context was saved.
This is an error, which I'm ignoring.
Don't really need to do this
for your UI managed documented, but it doesn't hurt.
You can do it if you want.
This would not break anything if you had a context
from UI managed document, but mine's not,
so that's why I'm explicitly saving here
after I load some photos in, okay?
Okay, so that's cool.
So, let's go look at our tables.
What is our tables, public API, managed object context?
We never set that.
Okay. We need to set this tables managed object context.
Okay. When and how are we going to do that?
We have this application delegate.
It's kind of this global thing,
and it is managing this global database, but it needs
to be able to communicate this thing out to anyone who needs
to use it, and the way we're going to that is,
whenever we set this photo database context, we are going
to post a notification, the radio station thing.
So, this is the first time you're going to see how
to post an notification, not just listen with that observer,
you're going to actually post it right here, so let's do that,
and when you post a notification you almost always 100%
of the time, want to create a header file, so I'm going
to create a header file.
Just go here to header file, C, C++ header file,
and that header file is going to contain the name
of the notification, and also the name of anything that's
in the user info, for the notification.
So, let's go ahead and make sure it's in the right place.
It is. I'm going to call this photo database availability,
because that's what this notification is about.
This radio station talks
about whether the photo database is available, so I'm going
to create this header file, and inside this header file,
I'm just going to put pound defines.
One is photo database availability notification.
That's the name of the notification.
I'm going to call it this.
I can call it anything I want, but I'm going to call it that,
and then also when the notification goes out,
I'm going to include the context in the radio station broadcast,
so the person can just get it when they get the notification.
I'll do that with photo database availability context.
And, I'll use the same, well, just say context.
It can be anything you want it to.
Okay, so this is going to be the name of the notification.
This is going to be the key into the dictionary of information
that comes along with the notification, alright?
So, now, let's send that notification, and I'm going
to do that every time we set this photo database context.
Question?
[ Background Conversation ]
>> Oh, yeah, probably.
Good point.
Yeah, no equals there.
Thanks, very good.
This is just a pound sign defined.
If it was a constant, we wouldn't do that.
Okay, alright, so let's set this photo database context,
so in the set; I think I might have a thing for that actually.
Set photo data.
Yeah, I do.
So, here when we set this photo database context, we are going
to post this notification.
And we do that using the NS Notification Center default
center, post notification name.
We just specific the name, which is this.
For this to work, we need to import that photo availability,
photo database availability header, okay?
So, we're just going to post this notification,
and we're going to give this user info along with it,
and these are info, it's just a dictionary that has one key,
which is that context, and the value
of that key is the context.
Okay. So, this is how you post in the radio station model.
Any questions about that?
And now, I'm going to show you listening to a radio station
without having to create another method and all this stuff,
basically really straightforward listening,
and who needs to listen to this?
Well, this guy does, this photographer guy,
he needs to listen to it.
So, basically, as soon as this guy awakes, and I might do this
in it with style, or whatever the designated initialize is
for TableView, but I'm just going to it in a wait for nib
for here, because we know this TableView is coming
out of the story board.
I'm just going to say, notification center.
First let's import that availability thing.
So, I'm going to do NS Notification Center,
default center.
Watch this.
Add observer.
Normally, we do it with a selector and all this stuff.
I'm going to do a block-based one.
I couldn't show you this before,
because you didn't know block, but it's this one.
Add observer for name, and we give the name,
which is photo database availability notification.
The object is who can send it,
and I'll let anyone send this to me.
It's going to be the app delegate,
but it could be anybody.
The cue, I'm going to do it on the cue that I'm on now.
That's what nil means, but I could say NS Operation main cue,
or some other cue even, but I'm going to say nil,
which means whatever cue I'm on right now
when this is being executed, using block, so I'm going
to double click here to put a block.
Okay, and then that's the end of that,
and what's going to be in this block?
This is one line of code.
Self.manage object context equals this notification,
its user info, photo database context.
Okay. Sorry for the very, very long line there.
I think it will fit, yeah it will.
Okay? So, I'm getting this block.
It's executed whenever this radio station broadcasts,
and because I put this user info of the context,
now I have the context,
and I just set my own managed object context, and voila,
it's going to load this table.
Questions about that?
So, that's notifying both on posting and receiving.
Alright, so now hopefully it will work.
Let's go take a look at this, and there it is.
Okay, now it went really fast there,
because it actually did the load last time,
but we just didn't see it, so the database was loaded.
So, I'm going to show it what it looked like to load up.
So, how do I clean this out?
Okay, how do I clean my database out?
So, really watch this, okay?
If you want to get rid of your database,
especially if you want to change its schema.
Because if you change its schema, and then you relaunch,
it's going to say incompatible database type.
So, if you want to get rid of it, just press the home key.
I also recommend quitting in X code first.
Then press the home key, hold down, press to hold,
you can do this on your device too, and then,
you get these jigglies, and then press the X
to delete that application.
That will delete the entire application,
including the database, and now, when I launch again in X code,
it is going to start up blank,
doing the Flickr Fetch in the background.
When that manage object content is filled up with data,
it magically automatically appears in the TableView.
That's because that Fetch Results Controller is watching
the context.
Okay? Questions.
[ Background Conversation ]
Yeah, let's go back and look at that.
The question is where did I set this user info,
this little user info right here, where did I set that,
and that was when I posted the notification here
in my app delegate, which I did when I set the context,
which I did when I launched.
Right, so I launch.
Here's launch.
When I launch, I create the context, you're going
to create it with U unmanaged document.
I set right here.
This is the setter for that.
Okay, I set it.
Then I post it to available to everybody else.
Okay? Question.
[ Background Conversation ]
Yeah, so the question is, how can I make sure
that the view controller exists, and is listening in time
to hear this, because the application delegate is posting
this pretty early, right after launch.
It's sending out this notification, and the answer
to that is that's why I do this in awake from nib, really early
in the view controller's life cycle, right?
When it's first created, so it has the maximum chance
of getting it, but it's possible.
It's unlikely, but it's possible
that some view controller you might create later
in time might need it, and in that case,
you might need a different mechanism, or you might need
to report or you might need to pass it along.
Okay, a lot of times, we don't want to use this mechanism
to give the context to view controllers,
exactly because the view controller doesn't exist yet,
until when this availability happens, it's not even there.
So, there are other ways to pass you manage object context
around, and you always want
to use those before a way like this.
Okay, and I mentioned that in the hints, so the homework is,
pass the manage object context
to a view controller that's NS vector results controlled
in a sensible way in a way that makes sense.
If you're segwaying to it, pass it to it by preparing it, right?
You wouldn't want to rely on something like this.
Okay. Alright, now let's talk
about loading our database some more.
Okay, right now, we only loaded our database on launch.
Here's the application that did finish loading with options.
We load our database right here and Flickr fetch that's it.
Okay? Well, that's not very good,
that just means we only get one batch of data ever,
when we launch our app, we have to quit,
or have to relaunch it all the time.
So, what about kind of loading this Flickr information
in the background, and we can do that,
but there's really two different background conditions
to consider.
One is background, and our app is in the background.
In other words, the user is not currently using our app, okay.
They were using it, but now it's in the background.
Okay, how do I fetch when that happens.
Well, fetching there is kind of limited by the system.
The system is not going let you just go hog wild fetching things
when you're not the app that the user is using,
but it will let you do it sometimes, okay?
And, the way you can get the system to kind of wake you up
and let you fetch sometimes in the background,
every once in awhile, I don't know, a few times a day,
who knows what, but sometimes, it's using background fetching,
which is a multitasking API, new for iOS 7.
So, I'm just going to show you this as an example of what some
of the multitasking APIs look like.
Now, the way you turn this is on, is you edit your project.
You see this is my project I clicked on up here,
and now you're going to go
to this tab right here, capabilities.
So, I go to capabilities, and there's a lot of capabilities.
This really kind of gives you a feeling
of how we're only skimming the surface of iOS, when you look
at all these things you can do.
But, anyway, we're going to do this one right here,
background modes, and I'm going to turn this on.
When I turn it on, there's all kinds of background modes,
things that I can be allowed to do in the background.
That is to say when my app is not currently being used
by the user, and I'm going to pick this one down here,
background fetch, and if I turn this on, okay, background fetch,
then I will occasionally by the system at its discretion,
send a message to my app delegate,
perhaps even launching me to do it.
Okay? And what is that message that gets sent.
I'll show it to you right here.
It is called, we're going to type it in.
Application, so you can look at all the things you can receive
from your application.
There is just a billion of them here.
See them, okay?
So, we'll cover some of those, but not all of them,
but there's quite a few of them in here.
But, the one you get when you do this is this one right here,
perform fetch with completion handler, okay, so this gets sent
to you, and it's basically saying, okay,
I'm giving you an opportunity to go do something
in the background, a fetch or whatever you want to do.
Usually it's a fetch, but you can kind
of do whatever you want here,
and the only responsibility you have in doing this is
to call this completion handler when you're done.
That's the only thing you absolutely have to do.
If you don't call that in a timely manner,
the system will grow tired of you, and it will stop fetching.
It will stop sending you this message.
So, more timely we respond to this, the more likely it's going
to let you fetch in the background.
Okay, so what are we going to do here?
Well, it turns out, all we're going to do
in here is start a Flickr fetch, and then we're immediately going
to call this completion handler.
We're not done.
This fetch, we just started it.
It's going to take awhile to come back later, but we're done,
as far as this background fetch thing is continued.
Okay, getting the result and doing all that, that's going
to happen at some other time, but here, we're done,
and we have to, the argument
to this completion handler is a UI background fetch result,
which is whether whatever you did in here changed your UI.
Because if it did, we need to update the little task switcher.
Okay, does everyone know what the task switcher is in iOS 7?
It looks like this, okay, here's the task switcher.
It lets you go through and look at very apps,
if my apps are doing anything here.
Let's launch an app.
Let's launch safari here.
Okay, so now I go into task switcher, and here's Safari.
See how it's showing me what's actually in Safari?
It's not really showing me what's in Safari right now.
It's kind of showing me Safari the last time I left Safari.
Or, if I get this background fetch
and this completion handler, I say UI background fetch,
new data, then it would redraw that thing for me.
It would give me a chance to redraw it.
But, I don't actually have any new data.
I have no data here, because I haven't gotten the data
from this yet.
This Flickr fetch has not come back yet,
so it's not going to do anything.
Okay? So, this is great.
This lets me occasionally fire off a background fetch,
but when the data comes back in, then what do I do.
Well, if I'm in the background,
none of these URL things are going to get called.
Okay? Because I'm back-grounded.
Now, it's not strictly true that these won't get called,
because what will happen is if the URL returns while I'm
in the background, so I started it in the background,
if it returns, I'll get another application thing called
application handle events for background URL session, okay?
And, it also has a completion handler, a little different one.
Okay, so this is called whenever things happen in the background.
Now, what's interesting about this one is,
I don't actually need to do anything in this one either.
Because if I implement this method,
then these delegate methods
down here will automatically get called,
and they already know how to unpackage the data from Flickr
and put it in my database.
They already know how to do all that,
but I still do have this responsibility
for the completion handler on this one too, okay?
Now, this completion handler, we really do want to wait to call
until we've actually handled this URL coming back
from Flickr.
Okay, this is handling a URL coming back from Flickr.
So, now we're going to wait.
So, I'm going to have to hold onto it.
So, I'm going to.
I have an instance variable here, where I'm going to hold
onto this completion handler,
and here's the instance variable right here.
Okay. It's a void.
It takes no arguments, just properties.
All blocks by the way, want to be copy properties.
Blocks want to be copied into the heap
when you keep a handle to them.
Something to know.
So, anyway, all I need to do is keep this thing, and then I need
to call this when I'm done, so I have a method down here
that I use to do that with.
It's called Flickr download tasks might be complete,
because I might have multiple download tasks happening,
and so what I do here is, I get all the tasks
that my Flickr download session is doing,
that's what this method does, and it has a little block
that gets called, because it can't do that immediately.
Sometimes it takes a little time to figure that out,
and then if there are no download tasks left, right?
Not download task count, then I'm going
to call this completion handler.
This Flickr download backload background inclusion handler,
and say that I'm done.
Okay, so now I've finished downloading it,
I've redrawn my UI, and I'm calling the completion handler,
and this completion handler doesn't have the little UI no
data thing, because it always assumes that you're going
to update your UI, okay?
So, it's always assuming.
It's always going to redraw when you do that.
Okay. So, let's see what this, okay, to see what this is going
to look like, there's a really cool way.
Well let's, okay, let's do this two part here.
I'm going to run this.
Here it is right here.
You can actually simulate fetching
in the background in X code.
So, I'm going back to X code.
Here's my UI.
Okay, I'm going to say, from X code, under debug,
simulate background fetch, and watch what's going to happen
to my UI, oop, I got put in the background.
Okay. And it's doing a fetch.
It's going in Flickr.
It's downloading to Flickr and doing all that stuff,
and actually if I went like this when it was done,
I would see the results in here.
Okay, now that's hard for you to see here, so I'm going
to show you another way
to simulate a background fetch besides this,
so let's delete photo mania so that our tables are empty.
You'll really be able to see it clearly here, oops,
I should have quit X code first.
Put that in the step.
And, so what I'm going to do here is there's a way
to launch your application as if it just got launched
from a background fetch, and the way to do that is edit scheme.
If you edit this little scheme,
the scheme is how it's launching you.
In this case, it's launching us in a simulator.
So, if you edit scheme, and you go over to options,
there's this little switch here,
launch due to a background fetch.
In other words, when I hit run, pretend I just got launched,
because a background fetch got sent to me, okay,
so that's what that means.
Now, normally, we're not going to set that switch
and leave it set like that.
You can actually duplicate this scheme, so I have the schema;
I'm going to duplicate it.
I'm going to call it my BFF scheme.
That means background Flickr fetcher.
It's my BFF scheme, and in my BFF scheme, I'm going to have
that switch set, okay.
In my other scheme, if I go back to this scheme and edit it,
that switch is not set, okay.
So, if I want to pretend that's happening,
I go to my BFF scheme, and I press run.
Now, when I run, see it ran me in the background.
So, the other two things -- the other thing I really wanted
to show you here, which I don't really have time to do.
Oh, actually I'll do it real quick is, how about fetching
when I'm the foreground app.
What happens if the user is currently using me,
and I want to fetch periodically.
Okay, that's a totally different thing.
To do that, we're going to use a class called NS timer.
Okay, so I'm going to put this here.
Once the database context is available, then I'm going
to fire off a timer using this NS timer method,
schedule timer with time interval.
I want to do this one.
How often should we do our Flickr fetch?
Well, it doesn't seem like Flickr updates it more
than once every 10 or 15 minutes,
so let's do it every 20 minutes.
So, this is in seconds.
So, I'll do 20 minutes, and the target is going to be myself.
In other words, every 20 minutes, send me a method,
and the method to send me is start Flickr fetch,
and the argument.
And, no user info.
Sorry, this has to be a colon.
I'll show you why in a second.
And repeat, yes, so I want this to just be every 20 minutes
at sending this timer.
Okay. So, why is this start Flickr fetch here have
to have colon?
That's because this timer when it sends its message,
it always has an argument, and if I do start Flickr fetch
with the argument, it's the NS timer that sent it to you.
But, in this case, I don't care.
I'm just going to start Flickr fetch.
So, every 20 minutes, I'm going to fire off this Flickr fetch.
Okay, so that's easy.
So, if you're in the foreground, now this timer will not fire
when you're in the background.
It just will not fire, but that's okay, because we have
that background fetching thing firing it,
not as often, but occasionally.
Okay, but now all the time,
our app is getting new Flickr information all the time.
Make sense?
Okay, so that's all I wanted to show you.
Hopefully.
There's a lot of information there I know.
We have background fetching.
We have foreground fetching.
You've got creating the database model.
You got doing the categories to create the adding things.
We got the TableView with NS Fetch Results Controller.
I'm going to post all this code.
I'll throw some comments in there tonight,
so you can remember what all these things do,
and you'll be good to go.
Alright? Good luck with your homework,
and I'll see you on Monday.
>> For more, please visit us at Stanford.edu.