[MUSIC]                         
Stanford University.            
>> Well,                        
welcome to Stanford CS193P,     
fall of 2017 and                
18's Lecture number 15. And     
today we have three topics for  
you, one is Alerts and Action   
Sheets. So that's a way of      
kind of notifying the user      
when an extraordinary event     
happens, or to help your user   
make a branching decision       
where to go now in the app,     
where it's kind of, you know,   
two or three choices            
of where they can go.           
The second thing we're gonna    
talk about is Notifications     
and KVO, that's a way of        
communicating blind and         
structured inside of our        
MVC and then finally,           
I'm gonna talk about            
the Application Lifecycle.      
We already talked about         
the view controller lifecycle,  
now we're gonna talk about the  
lifetime of your application.   
All right, so                   
let's start with Alerts and     
Action Sheets. These two        
things are very similar,        
the API to use them is almost   
identical, so I always talk     
about them together. They're    
a little bit different,         
an alert, it pops up in         
the middle of the screen.       
They're both modal, they kinda  
take over your screen but,      
alert pops up in the middle.    
Generally, whatever the alert   
is telling you or asking you,   
you're only gonna have one or   
maybe two choices to respond.   
It would be unusual to have an  
alert, even with three buttons  
in it. It's usually for         
asynchronous things,            
things like a network failure   
or something that happens out   
of the ordinary. You don't      
wanna use an alert as just      
a way to talk to your user and  
ask them a yes or no question,  
things like that. Alerts are    
pretty disruptive to the user   
interface experience because    
they lock out the entire app    
and force you to deal           
with this thing.                
So it's not a primary,          
kind of user                    
interface element,              
it's more of an emergency       
situation, asynchronous,        
unusual, that kind of thing.    
Now an action sheet is similar  
in that it's modal, takes over  
the screen, but here you're     
almost always gonna have more   
than two choices. This thing    
slides up from the bottom,      
you're gonna usually have two,  
three, four, five choices,      
even. And here what you're      
doing is asking the user to     
make a branching decision.      
Maybe they've asked             
to take a picture,              
to get a picture in their app,  
and you wanna know,             
do you want it                  
from the camera or              
do you want it from             
the photo library, or           
do you want it from             
somewhere else?                 
So they're kind of              
branching right there and       
you can't really help them      
until they make that decision   
for you, so that's what an      
action sheet is for. It's not   
like an alert in that it's for  
unusual circumstances,          
it's kind of normal branching   
decisions that you would have   
to make. So here's what         
these things look like,         
an action sheet slides up       
from the bottom like that,      
and it can have pretty much     
any number of buttons although  
obviously, you wouldn't want    
it to fill the whole screen.    
And then an alert,              
you've seen those,              
they come up in                 
the middle of the screen,       
they might even have a little   
text field in them as well.     
So, again, the API for          
them, i.e, using them,          
the code you write is almost    
identical, so let's just        
talk about one of them first    
which is actionSheet. Now,      
the way both of them work,      
they're just UIViewController.  
There nothing                   
special about them,             
they're just                    
UIViewControllers.              
You know, we learned about how  
to present a UIViewController   
modally in the last lecture,    
when we put our emoji art       
controller document             
up modally,                     
it took over the whole          
screen until we said done.      
Same thing here                 
with alerts and                 
action sheets.                  
This UIAlertController is       
a UIViewController and we're    
just gonna present it using     
exactly the same method we      
did to present our document.    
It's called present, but we're  
not gonna create it by getting  
it out the storyboard like      
what we did with our document.  
We're gonna create it           
with this initializer,          
UIAlertController title         
message preferredStyle. And so  
the title is just the title     
you can see on the left there,  
the image where                 
the title goes, right?          
It's the little thing at the    
top Redeploy Cassini, and then  
the message goes below that     
issue commands to Cassini's     
guidance system. And then       
the preferredStyle is either    
actionSheet or alert. So,       
this is what it looks like for  
actionSheet. Now, you           
create your actionSheet and     
then you want to add actions,   
these actions correspond to     
the buttons. So, we have four   
actions right there in our      
example in what we're gonna     
control Cassini here, and so    
we're gonna have four times     
we're gonna call a addAction.   
The argument to addAction,      
there's only one argument,      
it's a UIAlertAction.           
Which is another object and     
let's take a look at            
the initializer for             
UIAlertAction. It takes         
a title, that's gonna be        
the title that appears on the   
button, a style, we'll talk     
about the styles in a moment    
here, and then a handler, and   
a handler is just a closure     
you're gonna give it. It takes  
the action as an argument so    
that it's in your right hand,   
and you're gonna do whatever    
you do when that button gets    
clicked. So,                    
this alert in action,           
sheets have a very simple API,  
you just put these buttons and  
the code that goes              
with them on each one.          
So this handler for, our first  
button there, Orbit Saturn,     
was just kind of a normal       
button, so its style is         
UIAlertActionStyle.default.     
And the handler in there,       
I'm just going to go into       
orbit around Saturn. And        
that's someone, presumably,     
pressed this button once,       
and Cassini did that,           
it's finished now,              
but it did that at one point.   
So this is just the normal      
default, action here to         
orbit Saturn, right?            
And I can add another action,   
maybe Explore Titan, now,       
okay that's not                 
Cassini's mission, but          
maybe we could allow it if we   
let, make the person logins.    
So in the handler there, I've   
asked them to log in to verify  
they really want to divert      
Cassini to Titan, right?        
How about the next one, which   
is the Closeup of the Sun?      
Well if I really wanted to      
send, this Cassini off to       
the Sun, that would almost      
certainly destroy Cassini.      
And that's why it has a little  
different style there, which    
is .destructive, you see where  
it says style .destructive? So  
a .destructive item is gonna    
show up in red text right       
there and it's any choice       
that is going to make us,       
kind of significant             
unrecoverable action happen.    
you're gonna delete             
something out of a database.    
For example,                    
That might be a destructive     
action, obviously crashing      
Cassini into the Sun, that      
would be a destructive action,  
so that's what .destructive     
style is there. And             
then, finally, we have this     
cancel action at the bottom,    
you see it's kinda              
separated a little?             
And its style is different,     
.cancel, that's what it causes  
it to be separated. But a very  
important other thing about     
.cancel is that on the iPad,    
this thing is not gonna slide   
up from the bottom. It's gonna  
appear in a popover,            
which we haven't talked about,  
and we're gonna talk            
all about on Wednesday.         
But a popover is also modal,    
kinda takes over the screen,    
but it appears in a little      
window and, in there,           
you can't have                  
a cancel button,                
cuz a popover is cancelled      
by touching somewhere else.     
A popover comes up,             
if you wanna cancel it,         
you touch somewhere else so     
you don't need a cancel,        
you don't wanna cancel button.  
That's why it's important to    
note which of your buttons      
are a cancel button, so         
that when this                  
appears in a popover,           
the action sheet here won't     
include that cancel buttons.    
All right, so                   
we've added our four buttons,   
now we want this thing to       
slide up to the bottom and      
let the user choose and         
execute the appropriate         
handler and we do that          
with that same method,          
present. It's a ViewController  
method, present,                
presumably the ViewController   
behind there, you can see that  
it's got the picture of         
Cassini. That ViewController    
is presenting this action       
sheet and it's, you know,       
present the view controller,    
animated true, almost always,   
and then completion handler     
if you want for which will      
get called when the animation   
finishes. So that's it,         
super easy to use an alert.     
Now let's talk about, this is   
an action sheet, by the way.    
So let's talk about what it     
looks like on iPad, though,     
I said it was a popover, this   
is is what it would look like.  
In this case, you see that      
little redeploy button?         
And it's kinda small font, but  
it says redeploy in             
the upper right of the iPad.    
When I click that, this         
action sheet presented well,    
first of all how do I get       
it to present like that?        
And then second of all,         
how do I get it to point to     
the little redeploy button.     
So I have to do both of those   
things. The first thing I'm     
going to do is make it present  
like a popover. And             
to do that, I set the alerts,   
which is a view control         
remember, I set                 
it's modalPresentationStyle to  
be .popover. And that's gonna   
make it to represent as         
a popover. But that's not       
quite enough because I have to  
make a point at that little     
redeploy bar button item.       
And the way I do that           
is I get the alerts popover     
presentation controller,        
which will be nil if you're     
not presenting it as popover.   
And one of the vars in          
a popover presentation          
controller is the barButton     
item that is presenting it.     
You can also specify            
a rectangle,                    
an arbitrary rectangle and      
the little triangle will point  
at that when it appears.        
You can also specify which      
direction the little arrow is   
allowed to point, left, right,  
up or down. And in that way     
you can control the way         
that this popover presents.     
Does this make sense?           
Now you're probably saying,     
well I need to put if I'm on    
iPad then do this around this,  
right? Because obviously        
on an iPhone I don't want       
this thing to be a popover.     
But actually, you don't have    
to do that, because this exact  
same code will still slide up   
from the bottom on an iPhone.   
Now, why does that happen?      
We've specifically asked for    
the popover presentation style  
there and we specified the      
barButton item and all that.    
Well, iOS automatically does    
what we called adapting         
to the environment its in.      
Both the trait environment,     
right, compact width and        
or not, and                     
all that stuff we talked about  
before, but also the platform   
its on to some extent.          
And so here it notices,         
well I'm on an iPhone,          
I don't do popovers. Actually,  
you can do popovers on iPhone   
as we'll talk about, but        
you have to do extraordinary    
things to do that. So           
in the normal case of events    
it doesn't do popover,          
so it comes over in             
it's normal way. So             
if you're doing a popover, and  
you have a universal app that   
runs on both iPad and iPhone,   
you're gonna put this modal     
presentation stuff in there.    
All right, so                   
let's talk about alert.         
Same exact constructor,         
you just say preferred style    
alert, same exact               
adding actions. And             
here I am adding                
my cancel button,               
I'm marking it as .cancel plus  
importing in alert because it   
doesn't hide the cancel button  
in any case cuz alerts look     
exactly the same on both iPads  
and iPhones. And then I'm       
gonna add another action here   
which is my login button.       
Now, my login button is going   
to use that text field,         
you see that text field? So     
how the heck did I get a text   
field to appear in              
the middle of my alert?         
Well, I just said               
alert.addTextField, and         
the argument to that add        
text field is a closure         
that passes the text            
field to you and                
allows you to configure it.     
This is a password for          
redeploying Cassini off         
to the Sun, or titan, or        
something. So I want it to      
have secure text entry, so      
I'm using the text field var,   
there is secure text entry      
which is part of the text       
input traits protocol that      
text field implements. And you  
could do this more than once,   
you can have more               
than one text field.            
I recommend against that, and   
I generally recommend against   
using an alert as a login       
screen. Don't do that for       
your final project.             
If you have a login screen,     
make it a normal part of your   
UI, don't have it be an alert.  
But anyway, once you get this   
text field added with this and  
configured, then how do you     
get the text out when someone   
types the text. Well in your    
handler of the action for       
login right there, I'm just     
gonna use the var that's in     
alert called text field,        
it's an array of all the text   
fields. I only have one so I'm  
going to get the first one and  
then I'm going to get           
the text out of it.             
Couldn't be simpler.            
All right, I almost hesitate    
to show you the alert with      
the text field in there         
because it makes you say,       
that's a great way to get       
text from the user, but         
again alerts are disruptive so  
don't use them for that.        
All right, and I'm gonna        
present this in exact the same  
way I presented the action      
sheet with the present method,  
which presents. Just all        
present does is it presents     
a view controller modaly?       
And of course this is a modal   
because the whole screen        
is dimmed out, except for       
this middle box.                
All right, and as I said,       
on the iPad,                    
alerts look exactly the same.   
There's no difference.          
So that's alerts, so let's put  
an alert in EmojiArt, just so   
we could see this in action.    
And here's the alert I'm gonna  
put in. Right now, EmojiArt,    
if you drag any image in        
to EmojiArt, it will work.      
And that's because I            
have that image fetcher,        
remember that and               
the image fetcher allows you    
to specify a back-up image.     
And so if I can't get           
the image from the URL          
with the image fetcher,         
no problem,                     
I'll use the back-up image and  
create a one on disk and        
use that as the URL.            
Well that solution doesn't      
work too well in iCloud drive.  
Because I create an EmojiArt    
document on my iPad,            
I drag in something that I      
couldn't get it's URL so        
I just put the image locally.   
I put it on iCloud Drive,       
I go over to my iPhone,         
I look at it, I can't see it.   
Because it's using the backup   
image which is on my iPad. So   
I'm gonna fix my EmojiArt       
just to simply not accept       
those things. So if you drag    
in something that I can't get   
its image from the URL,         
I'm just gonna reject it.       
Now I could just quietly        
reject it. And the user would   
probably be like, what's going  
on? I keep dragging this and    
it won't take it.               
But it'd be much better         
if I put up an alert and        
said, I couldn't get the image  
from that URL, sorry, okay so   
that's what we're gonna do.     
However, once I got used to     
that, then I probably don't     
want it coming up every time.   
Because I do get the feedback   
when I drag in a bad image,     
it just does nothing.           
And eventually I'll learn,      
that one I can't drag in,       
I'll have to pick               
something else. And so          
I'm going to have my            
alert have two buttons.         
One is keep warning me about    
this, and the other one is      
stop warning me about this.     
Those are the only two          
buttons on my alert. The alert  
is otherwise just going to say  
I couldn't get the image        
from that URL.                  
So that's what we're going to   
build so let's go do that.      
To our emojiArt, here we are.   
So here's emojiArt,             
if you remember, we do all of   
our image dropping down at      
the bottom here in our draft    
interaction delegates here.     
Right here is                   
the imageFetcher,               
here's what we dropped when we  
get the URL, we fetch it with   
the imageFetcher. But if we     
get an image, we use it as      
a backup image. So we're        
not gonna do this anymore,      
I'm gonna in fact, stop using   
the imageFetcher all together.  
So I'm just gonna comment that  
imageFetcher out. Instead       
what I'm gonna do is what you   
did probably in your homework,  
hopefully. And                  
what we did last week in, or    
the week before,                
in the ImageViewController,     
which I'm just gonna fetch      
this thing directly.            
Now one thing I have to be      
careful about here is I don't   
wanna block the main queue.     
And this closure, the one that  
load objects, plural, that      
I do on a session. This one     
is a convenience method,        
it calls on the main queue.     
So this closure is on the main  
queue doing this. So I do not   
want that, I want to dispatch   
off of the main queue. So I'm   
gonna do DispatchQueue.global   
queue. I'm gonna get            
do userInitiated, because the   
user did just drop this and     
is presumably asking me         
to go do it right now.          
And I'm going to                
asynchronously perform this     
block. And what I'm gonna do    
in this block is go try and     
fetch that image. So I'm gonna  
say, if I can let the image     
data equal trying to ask        
the data to get the contents    
of this URL, but I'm actually   
gonna use the image URL.        
As you learn in your homework,  
sometimes you gotta massage     
that URL a little bit to get    
the right thing out of there.   
And then I'm going to let       
image = UIImage from that       
data, if I can, imageData.      
And if I was successfully able  
to do all of that,              
and I'm doing this all          
in another thread, so           
it's nice I'm not blocking      
the UI. Now I can use this URL  
absolutely normally.            
Of course,                      
I wanna now dispatch back to    
the main queue. All right?      
Cuz I'm gonna do UI thing,      
which is I'm gonna say,         
self.emojiArtBackgroundImage =  
[url, image].                   
I'm also gonna do               
docself.documentChanged.        
This is calling the method      
that used to be called save.    
And then after the last         
lecture I told you I was going  
to use delegation to            
automatically track changes.    
Well this is one                
of the changes I                
have to track. If you change    
the background image,           
I have to let the document      
know that it has changed.       
And we're going to look at      
document change in a little     
bit later demo, today.          
It's exactly the same as save,  
I just renamed it               
document change. But            
we definitely want to do that   
in here. Now, here's the rub.   
Here's the alert magic.         
If I couldn't do that,          
if I was unable to get that     
image out of there. Now I       
wanna put up an alert instead   
of using that backup image. So  
I'm going to say here,          
self.presentBadURLWarning,      
and I'm going to actually       
pass the url along.             
Now why am I passing            
that url along?                 
I'm not gonna do this for time  
reasons, but you know what      
would be a really cool thing    
is someone drags something in,  
it puts up the alert. They're   
like, don't warn me again.      
And they say stop. But then     
they drag another one in and    
it doesn't work. Then they      
try a different one and         
it doesn't work. And they're    
like, it's broken. They've      
kind of forgotten that they     
said stop warning me that.      
So somehow you might            
want that alert to come         
back on. At some point, right?  
And what would be a cool way    
to do that? How about if they   
drag the same url in twice.     
Because that's them saying,     
drag it in. It didn't work.     
Why didn't it work? Let me try  
again. Well if they're trying   
again they probably             
forgot about that alert.        
Maybe, maybe not,               
but it's likely.                
So that's the kinda thing       
you can do in your UI that's    
a little tricky, that allows    
them to turn things like that   
back on without having to go    
to settings somewhere and       
turn it on,                     
which is really cumbersome.     
It's just kind of using their   
natural things that they're     
doing. In the UI, you can       
make decisions like this.       
So I just kinda want to give    
you just kind of a classic      
Does that make sense?           
example of that. So that's      
why I might pass this URL on,   
because I might want to check   
to see if it's the same URL.    
Now I'm not gonna do that       
today, for time constraints.    
But I just wanted to give you   
the idea you could do that.     
All right, so let's do          
our private func here,          
presentBadURLWarning for URL.   
And what am I                   
gonna do in here?               
I'm gonna create that           
alert and present it.           
That's why we're here,          
is to learn about alerts.       
So creating alert is just       
creating that view controller.  
So let alert =                  
UIAlertController.              
Why they didn't call it         
UIAlertViewController,          
I do not know. They did not.    
So UIAlertController, and       
the constructor for it here,    
we always want this one         
down here. You can see this     
one's that NS coder stuff we    
learned about before. This is   
is kind of an old style thing.  
We always want this one right   
here, that gives us the title,  
the message that's              
gonna go in there.              
And the style, whether it's an  
action sheet or an alert. And   
so our title here,              
what's happening?               
Well, they dropped an image.    
We couldn't get the data.       
So I'm gonna call this thing    
Image Transfer Failed, maybe.   
It's actually very important    
to pick good phraseology here,  
cuz you don't wanna freak       
your user out. My gosh,         
what did I do or whatever?      
You wanna try and               
give them something that        
gives them the authority,       
kind of project some authority  
that this, don't worry,         
this happened. I understand     
it and here's your options.     
But not something that's so     
technical that they're like,    
what? Like if we say something  
like couldn't load from URL.    
Okay well users don't even      
know what URLs are. So          
you wouldn't wanna              
put URL in here.                
You see what I'm saying? So     
image transfer, when they're    
dragging presumably they're     
trying to transfer that image.  
You know, it's a good name.     
Maybe we might even wanna say,  
image drop failed, possibly.    
You know, this is the kind      
of thing you user test and      
you try and get the right       
words. Of course,               
the other thing here is         
we wanna localize this.         
And I'm gonna talk, hopefully   
the week after Thanksgiving,    
about how to localize your app  
for other languages. Because    
we want our app to run in as    
many languages as possible, so  
we have to make that string     
be able to be localizable.      
And it's quite easy to do in    
iOS, but we'll learn about      
that in a couple weeks. And     
now here's the message where    
I'm gonna tell them more        
about what happened.            
So here I'm kind of saying      
what happened here, which is    
that I couldn't transfer the    
dropped image from its source.  
Again, I'm not mentioning       
the term URL or                 
anything like that.             
I'm just doing that. And        
of course this is an alert,     
not an action sheet, so         
we'll say that. So this         
creates this view controller,   
and then I'm just going to      
present I am a view controller  
here, present. So I can         
call this method on myself,     
it's a view controller method,  
present.                        
I'm gonna present the alert,    
animated true, and              
I don't have any completion     
thing I wanna do so I'll just   
leave that off. But of course   
I need to add my buttons here.  
So what buttons                 
are we gonna have?              
Well, remember I'm gonna have   
keep warning me and stop        
warning me. Okay so, let's do   
the keep warning one first.     
So I'm just gonna say           
alert.addAction and             
remember the action you can     
see takes us one argument,      
which is a UIAlertAction. And   
that has only one initializer,  
which is these one right here.  
So make it so                   
you can see even better here.   
All right,                      
so it wants the title. That's   
the title of the button. So     
this is the one where I'm       
going to keep warning           
the person. And the style for   
this is just default,           
this is the normal default      
button. Keep Warning isn't      
anything special, it's not      
gonna change anything, really.  
We just keep on warning them.   
And I actually don't            
need a handler here,            
cuz I'm not gonna do anything,  
if you keep saying              
Keep Warning me,                
cuz that's what                 
I do by default.                
So I'm just gonna get rid of    
that, and that's my action. So  
a lot of time cancel            
buttons and okay buttons,       
they don't have any action,     
they don't do anything. And     
that's, this is kind of like    
an okay button in a way. But    
our other button alert add      
action, UIAlertAction.          
This one does have a handler,   
and                             
let's talk about how we're      
going to implement this.        
Let's see, now it's on one      
page there. So here this, this  
string is Stop Warning. Now if  
I just have Stop Warning and    
Keep Warning, that's really     
not enough information for      
people to understand.           
What do you mean Stop Warning?  
You know what I mean? So        
I actually wanna add a little   
more to my message up here.     
I'm gonna say something         
along the lines of,             
show this warning               
in the future?                  
Now, Keep Warning and Stop      
Warning make a lot more sense.  
However, you don't              
want this to be yes and         
no. Having buttons in           
an alert, yes and no.           
That forces the person          
to go carefully read and        
parse the message you said.     
And they don't get any double   
check that they read it right   
before they press yes or no.    
So always try to pick things    
that are more descriptive than  
yes or no, like keep this       
warning, stop this warning.     
Okay you still                  
have to be brief,               
you don't want these buttons    
to have ten words on them.      
So it's a compromise            
between brevity and             
making sure the person          
understands.                    
Now I'm gonna call this         
destructive because it's going  
to stop it doing something      
that it does pretty much        
permanently unless I go         
add that feature where          
I compare the URLs and turn it  
back on. So I'm gonna set this  
to destructive. So it's gonna   
turn out red. It's gonna        
make the user think a little    
bit before they press that,     
which is exactly what I want.   
And how about our handler       
here. So the handler passes     
this action back to us. And     
we usually don't                
need that because               
we can just capture it in       
using closure capture,          
we capture this little action.  
Although, you know, since you   
usually add it like this, you   
don't actually have a local     
var to this action. So it's     
kinda nice that it passes it.   
We don't need it in any case.   
All we need to do here is set   
some var that says,             
suppress these warnings.        
So I'm gonna say self.          
suppressBadURLWarnings = true,  
so I need a var for this.       
So I'll put that up here,       
private var, I think I copy     
and pasted it, yeah I did.      
Equals, of course it's          
gonna start out false,          
we're not gonna suppress it.    
And all I'm gonna do is, not    
do this method if that's true,  
so I'm gonna say if             
suppressBadURLWarnings,         
not then do this. So            
that's it, that's the entire    
implementation of this,         
let's go see this working.      
Here's our app right here,      
let's open up our Apple Bees    
document right here. Here it    
is, and let's try dragging      
in an image, that works.        
How about I think this one      
works, this one has an URL.     
So we drag it in, it loads      
it up, excellent, it worked,    
it's got a high resolution      
image, that's good.             
How about let's drag in         
one that doesn't work,          
how about this one? This one    
happens to not have a good      
URL, all right,                 
we got an alert here.           
Couldn't transfer the dropped   
image from the source,          
show this warning in the        
future, keep the warning, or    
stop warning, so I will         
keep warning. That's good,      
let's try another one,          
how about this one down here?   
That's also no good, now I'm    
tired of this warning, so       
I'm gonna say, stop warning     
me. Now let's try and           
drag this bad one in            
again right here,               
no warning. All right,          
so that's that,                 
let's get back to our slides,   
and                             
action sheet is exactly         
the same, right?                
You're gonna do exactly         
the same thing over there.      
All right, our next topic here  
is notifications and KVO.       
So if you remember back to      
the MVC talk I did at the very  
beginning, like, second         
lecture. I had this little      
radio station, the little       
orange things right there.      
I said, well, the model can't   
talk to its controller, so it   
has to use other mechanisms.    
And why can't the model talk    
to the controller? Because the  
model is UI independent and     
the component is                
fundamentally UI dependent.     
So there's no way for them      
to talk in that direction.      
The controller can talk to the  
model, but not the other way,   
so we have this blind and       
structured way of doing it.     
By the way, a view might        
also want to use this           
radio station to talk to its    
controller because the view     
can't also talk to              
its controller for              
a different reason. The view    
is generic, and the controller  
is specific UI. So there's      
no way generic items like       
buttons could know anything     
about a particular controller.  
So for both reasons, the        
viewing model ca't talk to      
the controller, controller      
talking to them is okay, but    
ca't do the other way. So       
they both could use this radio  
station model. And there's      
really two ways to do radio     
stations, notifications and     
KVO, KVO stands for             
key value observing.            
So we're gonna talk about this  
radio station, by the way,      
only I call it radio station,   
it's not called radio station   
in the doc. But a radio         
station is a good analogy for   
the kind of communication       
that's going on between these   
things. All right, here's       
notifications, the first of     
these. So a notification        
is essentially just             
a way you're gonna register     
a closure to get called when    
someone broadcasts on a named   
radio station. That's all it    
is, very simple, you can see    
how it's immediately blind.     
Nobody knows who's              
any classes,                    
all we're talking about here    
is this radio station. And      
it's very flexible,             
cuz you just plop a closure     
down there, and it just calls   
it when someone broadcasts      
on that radio station. And      
it's also possible to           
broadcast music on a radio      
station. In other words,        
when you broadcast,             
you can put information across  
the radio station as well,      
which is kinda cool.            
All right, so this is what      
the function to say I wanna     
listen to a radio               
station looks like, this        
code you see up right here.     
All of this stuff is done via   
this thing right here,          
NotificationCenter.default.     
You see that                    
NotificationCenter.default,     
and I'm using it down here. So  
NotificationCenter is a thing   
that you use to both sign up    
to listen to a radio station,   
and to broadcast on             
a radio station. And            
we always just use this         
default shared instance of it,  
kind of like user default,      
remember that one?              
We had userdefault.standard,    
we just used the shared one,    
same thing here. So             
this method to say you wanna    
listen is called addObserver.   
You're essentially going to     
observe this radio station,     
to listen to see if             
anything is broadcast           
there. And you see it has       
a return value there, which is  
of type NSObjectProtocol, I'm   
gonna cover that in a second.   
But first let's look at         
the arguments to this thing.    
First of all, we have forName,  
you see this, right, forName,   
Notification.Name, that's the   
name of the radio station. And  
notice it's type                
is not string,                  
it's Notification.Name. And     
so if you, when you name it,    
you will have to create your    
own Notification.Name if you    
wanna broadcast on your own     
radio station. Which is fine,   
you wanna give your radio       
station a unique name. But      
if you wanna look and find      
the radio stations that exist   
already in iOS, and there are   
dozens of them. iOS is very     
good at broadcasting on         
a lot of radio stations.        
You can just go look in         
the documentation for           
Notification.Name, and you'll   
see them all listed there.      
What they do, when they         
broadcast, that kind of stuff.  
So that's why it's nice that    
they made it not a string,      
but a type that you can go      
look up in the documentation.   
All right, the next thing       
is this object Any?.            
That is who's broadcasting      
on this radio station,          
because unlike real             
radio stations,                 
multiple people can broadcast   
on the same frequency,          
and that's perfectly allowed.   
And this just says who          
is broadcasting at the, who     
did the broadcast that you're   
receiving when your closure     
gets called here. And           
then you see right there,       
we have the queue,              
this OperationQueue. That's     
what queue do you want your     
closure to be executed on.      
Now, this can be nil, but       
you almost never want nil.      
What nil means is,              
execute my closure on the same  
queue as the broadcaster.       
You do not want that usually,   
unless you're the broadcaster,  
if it's your own code, and      
you're doing the broadcasting,  
maybe you want that. But        
if you're listening to          
something from iOS, for         
example, no, you probably       
want the main queue. Now,       
notice that says operation      
queue, not dispatch queue, and  
I actually mentioned this when  
I talked about dispatch queue.  
That there's an object          
oriented API to doing all that  
dispatch stuff, called          
Operation and OperationQueue.   
Well, this is using that        
object-oriented API,            
if you want the main queue,     
which is what you               
want 99% of the time,           
just say OperationQueue.main.   
The same way you say            
DispatchQueue.main, you can     
say OperationQueue.main. And    
then the last argument to this  
addObserver is the closure you  
want to execute. And that       
closure only has one argument,  
which is a notification. A      
notification is just a little   
object that has, for example,   
the name of the radio station   
and who the broadcaster is.     
But it also has a very          
important piece of              
information called userInfo.    
userInfo is the music that's    
being broadcast to you,         
it's almost always,             
it's a type any, but it's       
almost always a dictionary.     
And when you look in            
the documentation notification  
name to find all                
the radio stations.             
They will say,                  
when we broadcast,              
we include the following        
keys in the dictionary, this    
information. So that's a very   
important piece to understand,  
is that your closure has this   
one argument, notification.     
You look at the var userInfo    
in that notification to get     
the music that's coming across  
the radio station right now,    
all right? Now let's talk       
about that return value,        
you see that                    
observer up there?              
Notice that really weird type,  
NSObjectProtocol,               
what the heck is                
NSObjectProtocol?               
NSObjectProtocol is a protocol  
that NSObject happens to        
implement. It's a subset of     
the functionality of NSObject   
that some objects implement     
that aren't subclasses of       
NSObject. So that, you know,    
this kind, this well-known      
set of things. However, that's  
completely irrelevant here.     
Does not matter. That thing     
might as well be in any as far  
as you're concerned. All this   
thing, this observer thing is   
a cookie that just keeps        
track, that basically this      
observation is this thing.      
So, it's just a cookie for      
you to hold on to.              
You only do one thing with it,  
which is stop observing.        
It's how you say                
I don't wanna listen to that    
radio station anymore. And      
you do that by asking the       
NotificationCenter.default to   
remove observer, this cookie.   
And it will stop listening. So  
we'll show you an example       
of that in a second.            
Quickly on Notification.Name,   
all of the notification names,  
they collect them as static     
lets, little static let         
constant Notification.Names in  
the Notification.Name class.    
By the way, you'll often see    
it called NSNotification.Name.  
That's the same thing.          
They're literally type aliased  
to each other. You know,        
in the Swift world, we would    
call it Notification.Name,      
and in the Objective-C world,   
NSNotification.Name.            
Fine, they're the same exact    
thing. And again, if you wanna  
create your own radio station,  
we actually, or I recommend     
creating an extension to        
Notification.Name, and          
adding your own static let      
which is your thing, equals,    
Notification.Name, of some      
string, any string you want.    
That way you'll be collected    
in exactly the same             
kind of API realm as all of     
the other notification names.   
And you'll see that when we     
do the demo. All right, so      
here's an example of listening  
to the radio station.           
What's a good example?          
This is a great example.        
Remember,                       
the slider that said, set your  
font size, the accessibility    
slider? You can make it bigger  
and smaller? Well, you can      
find out, because there's       
a radio station broadcast       
anytime that changes. So        
that's a great thing to know.   
If you have something in your   
UI whose font is based on       
that, for example, we talked    
about doing the cool thing of   
having the collection view      
on the top of emoji art,        
having its emoji get bigger or  
smaller, based on this slider.  
Which would not be that         
hard to do. I'm not             
gonna do it as a demo but       
you can do it as an exercise.   
The main thing we would have    
to do is have our cell size     
be, fixed to this font          
size by doing our               
little font metric scaling.     
And we would also have to have  
a layout constraint for the     
height of our collection view   
that we wanna set in code to    
be the height of the cells.     
Because remember that our       
cells can't be larger than our  
collection view. So we'd have   
to make the collection view     
bigger and the cells.           
But we could easily do that.    
But if we did that,             
we would definitely want to be  
listening to this               
radio station.                  
Because every time              
that font changed,              
we'd have to re-layout our      
collection view, of course,     
all right? So here's            
what it would look like.        
We get the                      
NotificationCenter.default.     
We create this observer var     
which we set equal to doing     
addObserver. The name of        
that radio station is           
Notification.Name.UIContentSi-  
zeCategoryDidChange.            
That's kind of a mouthful but   
that's what it is.              
We're listening for that        
from UIApplication.shared.      
That's the application object.  
I'm gonna talk about that at    
the end of this lecture.        
You could also put nil there.   
Cuz basically if anyone         
broadcasts that thing changed,  
you're interested. So it would  
be fine to say nil here.        
That means if anybody           
broadcasts it. And then of      
course OperationQueue.main. I   
say or nil but really we would  
want .main there. Cuz we're     
not actually sure what thread   
this iOS would be               
broadcasting this on.           
So we want to make sure we're   
on the main thread when we      
do our stuff, and then our      
closure. Now inside our         
closure we cause our            
collection view to redraw.      
Whatever we do is fine.         
And also notice there,          
there's something, some music   
broadcast on this station.      
Which is, you can find out the  
content size category. And so   
there's names for               
all those detentes,             
in the slider there, like       
UIContentSizeCategorySmall,     
UIContentSizeLarge,             
UIContentSizeCategoryAccessib-  
ilityLarge, which               
is even larger.                 
And there's like very large,    
and extra large, I don't know.  
There's all kinds of different  
spots in there that you could   
look at if you wanted to. But   
you're probably not going to.   
You're probably in that         
collection example just going   
to resize your font based       
on the font metrics.            
Remember how we do that scaled  
font thing off the UI Metrics.  
You would just cause that to    
recalculate, all right? Now,    
notice that I hold on to var    
observer right there. And then  
I remove it when I'm done. So,  
it is a good question here.     
When do I add and when do I     
remove observing. Well, almost  
always you're doing this as     
part of something you're doing  
in the ViewController.          
So a perfect time and           
probably 90% of the time,       
when you get viewWillAppear or  
viewDidAppear, you              
add observer. And               
then on viewWillDisappear or    
viewDidDisappear,               
you remove the observer.        
That makes sense?               
Because you're only interested  
in really getting these size    
changes while                   
you're on-screen.               
of course, the size might       
change while you're offscreen.  
Now if you do that,             
So when you get                 
viewWillAppear,                 
you'll probably also wanna      
look at the size category,      
which you can do.               
UIApplication has a var for     
that. And adjust your           
collection view then            
before you appear. But          
it's kinda a waste for you to   
be listening to that thing all  
the time and changing things    
when you're not even on         
screen. So viewWillAppear,      
viewDidDisappear are great      
places to put add observer,     
remove observer pairs. Always   
pair these things. Don't        
forget to remove observer. How  
about broadcasting on your own  
radio station. How do you       
do that? You do that with       
the NotificationCenter.default  
as well.                        
The method there is called      
post. The first argument,       
the name, is the name           
of the radio station.           
You get to make that up. We've  
talked about how to do that.    
object, that's you. That's      
who's sending it. Usually       
that's self. You can make that  
any object that you want.       
But, that is who                
the NotificationCenter will     
report as the sender,           
the broadcaster.                
And then userInfo, that's       
your music. And that's, almost  
always, you're gonna want to    
put that as a dictionary        
of AnyHashable thing            
to an Anys. So it's very        
flexible, you can put anything  
you want in there. Now, as      
soon as you call this method,   
it will immediately call        
all the closures for            
that have addObserver           
to your radio station,          
with a following caveat.        
It's only gonna immediately     
call them If they               
specified queue nil.            
Cuz then it's gonna execute     
their closures on the same      
queue as this. So               
then it executes right away.    
If they specified a different   
queue like the main queue,      
then this is going to post      
their closures to execute.      
And it will execute             
as soon as that                 
queue gets around               
to their closure.               
So that's notifications.        
All right, KVO. Now I'm gonna   
spend two slides on this. But   
I wanna emphasize up front,     
this is not a major important   
thing you're gonna do this.     
Most quarters, I don't          
even talk about this. But       
I kinda decided to throw        
it in this quarter just so      
you can kinda know              
it exists out there.            
It's not really a primary       
way of doing things.            
Notification is much            
more of a primary way.          
This much less primary.         
And it's because, it's because  
it's kinda limited a little     
bit in its application.         
So what is KVO? The basic idea  
here is, when it comes right    
down to it, it's the idea of    
registering a closure that      
gets executed when a property   
on a sub-class of NSObject      
changes.                        
That's pretty much what it is.  
Now let's talk about some of    
the caveats I just put there.   
To make KVO work, you can't     
just have any property and      
you change it and someone       
can register a closure.         
Think about the overhead        
of doing that.                  
You would not want that for     
every property.                 
A lot of properties are         
probably they act as inlined    
by the compiler.                
So there's no way you would     
be able to do that. So          
there's a mechanism that's      
required to do this.            
Now NSObject, remember          
what NSObject is, right?        
It's the root of all            
iOS classes, right? So          
UIViewController, UIView, they  
all inherit from NSObject.      
So NSObject puts                
this mechanism                  
that makes it possibly to       
watch a property into it.       
So that's why I say This is     
for subclasses of NSObject,     
you could put this mechanism    
in your own object, however.    
It's not that difficult,        
I'm not gonna cover it, but     
people usually don't.           
They just use the mechanism of  
using NSObject by having        
their thing, whatever it is,    
their class,                    
subclass from NSObject. So      
that's the first                
thing to understand.            
There's kind of some mechanism  
there that you would have       
to implement if you didn't      
wanna subclass NSObject.        
What is this thing good for,    
what's KVO good for? Well,      
it's kind of good for some the  
same things as notification.    
Blind structured                
communication between things,   
especially between models and   
their controllers.              
But also between a view and     
their controller, or            
even between a view and         
itself, as you'll see in        
the demo here. Not every        
property works with KVO,        
as I said,                      
that would be ridiculous. For   
a property to work with it,     
not only do you need            
the NSObject mechanism, but     
the property has to be what's   
called key value coding         
compliant. Now,                 
what that means is,             
that property can be set        
by sending set value for        
key, where the key is the key   
path of that property, and      
get value for key to get it.    
In other words,                 
there's these functions, set    
value for key and value for     
key, that you can call to get   
the value of the property.      
That has to be possible         
on the object,                  
that has to work if             
you want do it. And             
that's called key value         
compoding, key value coding     
compliant. So that property     
has to be that way, now,        
you have to do some work to     
make that happen. Properties    
don't just magically make that  
work, you usually have to       
implement something like value  
for key and set value for       
key to make that work. Now,     
there are a few properties      
scattered throughout iOS that   
are key value observing,        
that work with key value        
observing. Most notably,        
in UI view, center and          
frame are key value observing.  
So you can observe the center   
or frame, and/or frame of       
a view, and you can find        
out when it moves, so           
that's kinda cool. Also,        
most of the properties in       
the CALayer underneath UIView,  
remember the place where we     
put the border                  
around the view,                
back in assignment three or     
something like that?            
That layer that's doing a lot   
of the drawing for UIView,      
that layer is mostly key value  
observing compliant. So you     
can observe things happening    
at that layer as well. And      
they are scattering other       
places, for example,            
core data. Remember core data,  
the object oriented database?   
Key value observing can         
be really big there.            
You could watch everything      
happening in your database      
on a per-property basis by      
using key value observing. So   
there are some frameworks that  
actually use KVO a lot. But     
for the most part,              
we don't use it in the main     
line that much. And of course,  
you could make your own         
NSObject subclass that          
implements this stuff.          
But that's way outside          
the scope of this class, and    
again, template sizing is not,  
this is not that huge a deal.   
All right, so how does that     
work, what is KVO look like?    
There's this one very           
important method that NSObject  
provides for you,               
called observe. So              
observe takes a keyPath as      
an argument and a closure, and  
it executes that closure        
whenever that keyPath changes.  
Only works for keyPath that     
are key value compliant,        
key value coding compliant.     
Notice that it returns          
a little cookie,                
our observation,                
you see that? It's a little     
different than a notification,  
though, you never say, remove   
observer on that cookie.        
Instead, when that cookie       
goes out of the heap,           
it stops observing.             
So as long as you want this     
observation closure to          
be observing that thing,        
just keep that cookie in the    
heap. As soon as you let it go  
out of the heap,                
it will stop observing. Now,    
the arguments you see to        
your closure, of course,        
you get the thing that's being  
observed, observed handed back  
to you. You also get            
this thing change,              
that change is of type          
NSKeyValueObservedChange. And   
that's a little object that     
you can get the old value of    
the thing, the new value        
of the thing that changed,      
that kind of stuff. It just     
basically tells you about       
the change that happened,       
that caused your                
closure to get called.          
This KeyPath argument is not a  
string, used to be in the old   
days. Nowadays, it's actually   
a typed thing in Swift, and     
it has special syntax, which    
is backslash, the type, dot,    
the name of the property. Now,  
Swift will infer the type for   
you, so we almost always say    
backslash dot the property. So  
for example, if we want         
to observe the center or        
frame of a view we would        
say observe \.frame.            
and that will be observing      
the view's frame. All right,    
so I have a demo of             
both of these things,           
notifications and KVO, so       
let's take a look at these.     
What I'm gonna do here is,      
remember after last lecture,    
I said, we don't want to have   
a save button in EmojiArt.      
We're gonna get rid of that,    
there's no reason to have       
a save button. Really,          
when we hit Save, we were       
just telling our UI document,   
something changed, so           
you should autosave soon.       
Really, what we want is to      
watch our EmojiArt view,        
and whenever an emoji           
gets added or resized or        
moved, we want to               
notify the controller.          
So the controller can tell its  
document, something changed,    
then we can just ditch          
the save button.                
Well, after lecture last time,  
I told you I was gonna          
do that, and I did.             
So the stuff that's posted has  
this in there, and what I used  
was delegation. And it did it   
specifically cuz I wanted you   
to see what it looks like       
to make your own delegate.      
You've been using               
scroll view's delegate,         
table view's delegate,          
collective view's delegate.     
I wanted you to see, wanted     
you to make your own delegate,  
so I created                    
an EmojiArtViewDelegate, and    
I'll briefly show you           
what I did there.               
And so that's great, but        
today, what I'm gonna do is     
use notifications instead.      
Because you can image,          
anything that's happening       
with a delegate,                
that's blind structure          
communication. Well, we can do  
that with a notification just   
by having a radio station,      
which is the EmojiArt view      
something changed radio         
station. And a controller will  
just tune in, and every time    
it hears a broadcast on that,   
it'll tell its UI document,     
something changed, that's what  
I heard on the radio station.   
And so that's what we'll        
do there, and then KVO,         
there's a great                 
use of KVO here.                
Which is, right now, I had to   
go down where my gestures are,  
remember, I dragged in some     
gesture code. I had to go in    
there, and for every time       
a gesture changed the position  
of an emoji, I had to tell my   
delegate something changed,     
tell me. So I had a lot of      
code in there for that, so      
I'm just gonna rip              
all that code out.              
And instead, I'm gonna observe  
the center of my emojis, and    
when my emojis move, or         
even when they're resized,      
because when they resize,       
they have to be repositioned,   
right? Cuz they grow from       
the upper left corner,          
so I have to keep               
repositioning, so               
I'm setting the center again.   
So                              
I'm just gonna observe that,    
and when that happens,          
then I'll broadcast on          
my radio station. So            
that'll collect that code into  
one place, and keep it from     
being spread out through all    
over my code in a messy way.    
But before we do that stuff,    
I'm going to do a simple        
notification thing, which is    
I'm just going to observe       
the state of my UI document     
changing. You know how our UI   
document goes through these     
document states, normal,        
closed, progress available      
when it's, say, reading and     
writing, saving, error,         
remember all those states?      
Well, we're gonna watch that    
happen, just to kinda get       
a warm up on notifications, to  
see what that looks like. So    
let's do that one,              
I'm gonna go up here,           
here's viewWillAppear, right    
here, and close. Right, so      
here's our document opening     
and closing up here. So         
all I'm gonna do here is, when  
my document first appears,      
I'm going to start watching my  
document. And it broadcasts on  
a radio station that tells      
me when its state changed.      
So what does that look like,    
well,                           
again, i need to capture        
the return values.              
So, i'm gonna call my           
documentObserver equals,        
let's go ahead and              
make a var for that.            
private var documentObserver,   
remember, it's                  
an NSObjectProtocol, optional.  
Again, this is the cookie,      
we never send a message         
to this, ever. We don't         
even not know what messages it  
responds to. So we're gonna,    
create this document            
observer here, I'm gonna do     
NotificationCenter.default      
That's how we do all of our     
stuff. And do addObserver, so   
here's addObserver forName,     
make this a little              
easier to read,                 
is what I want to do here.      
I wish they had                 
a little command key I could    
do that would do this for me.   
All right, so we're gonna       
listen to the document state    
radio station. So we,           
let's find the name of it.      
I'm just gonna type,            
Notification.Name., and         
you're gonna see how many       
radio stations there are in     
iOS. A lot, okay? And you       
can go look at all these and    
what they broadcast and what    
music they play and all these   
things. We've already talked    
about some of these things,     
for example, keyboard. Here's   
a keyboard hide, DidHide,       
will show. And then of course   
the content category size did   
change thing, right?            
There's that there.             
So, the one we want is          
UIDocumentStateChanged,         
you see the first one there?    
So UIDocumentStateChanged, so   
that's the radio station        
we want to listen to.           
We're only interested in        
broadcast from our document.    
That's the sender. That's       
who we want to broadcast.       
We of course want to be on      
the main queue here. And        
here's the closure that's       
gonna be executed when someone  
broadcasts on that.             
Here's our notification. Now    
this notification I think it    
actually does have some music   
on there, which is probably     
the document state. But         
I don't even need it cuz I've   
got my document right here.     
So I'll just grab its state.    
I'm just gonna say              
print.documentState changed     
to. And                         
we'll say are                   
self.documentState. I actually  
added a little extension to     
documentState right there so    
that it would print it          
out nicely .normal.close,       
those kind of things. Now       
anytime you start listening     
on a radio station, you         
immediately have to think when  
am I going to stop listening    
on this radio station?          
Well, here I'm starting even    
before my document opens, but   
I'm waiting until view will     
appear. So I'm going to stop,   
I could stop in view            
will disappear or               
view did disappear, but         
I'm actually going to stop      
when my document is fully       
closed.                         
Once it's fully closed,         
I certainly don't want to       
be watching it anymore. So      
let's go down here where we     
close. This is the close,       
here is where we closing.       
Right now we don't use          
the little success closure      
that happens when we close.     
But I'm going to star using     
it. Success in space,           
Return. And in here I'm         
going to remove observing       
this documentObserver.          
So I'm just going to say here,  
if I can let observer, server   
equal my documentObserver.      
Then I'm going to ask           
the NotificationCenter.default  
center to remove                
that observer.                  
In other words, stop observing  
that. Everybody cool            
with that? Everyone understand  
what I'm saying here, about     
this is the completion closer   
from closing the document? So   
once it's closed, that way      
we'll be able to observe it     
closing. It will be nice.       
So let's go run this and        
watch our console, so I got     
my console going down here.     
Actually, this is my console    
over here. All right, so        
let's run. All right, so        
here's our app. So we           
haven't opened any documents.   
So we have nothing on here.     
I'm gonna go ahead and          
clear out my console.           
So we haven't opened            
any documents.                  
So we haven't gotten any        
documents to exchange.          
So I'm gonna open our Apple     
Bees. Here is our Apple Bee.    
And look, documentState date    
changed to normal, right?       
Because we opened               
the document,                   
now it's in normal. Now,        
how about putting something in  
here maybe an apple, something  
like that. Now it's, where,     
what's going to happen to the   
state right now? Okay well,     
eventually it's going to        
autosave. It does it about,     
I don't know, once a minute or  
something like that. But        
when it autosaves, we're going  
to notice because it's going    
to go to state progress         
available. There it is,         
progress available and          
then back to normal. Because    
the progress is available       
because it's saving and         
it can tell you the progress    
as it saves, and                
then goes back to normal. I'll  
show you another trick. Here,   
you can force an autosave,      
by the way, by threatening      
to switch to another app.       
Watch this, I'm going to drag   
up from the bottom like, I'm    
gonna switch to another app.    
This caused an autosave. Now,   
it didn't do it here because    
we haven't made any changes.    
But this is a great way         
to make sure that you're        
changing stuff works.           
So watch this, now I'm          
gonna add a something here.     
Now when I do this threat,      
whoop,                          
it's saved. See what happened   
there? So when you threaten to  
switch to another app           
autosave will auto save.        
Cuz it's just afraid, my gosh,  
I might get killed or           
who knows what,                 
I better save. So               
that's a nice trick to          
know when to do that. And       
if we close this then we get    
state changed to closed. So     
this is cool. We just listened  
to that radio station,          
we're just reporting            
what happened.                  
All right,                      
now let's go ahead and          
have our emoji artview          
be a broadcaster.               
We are listening to UIDocument  
which is the broadcaster here   
and we are the subscriber       
to the radio station.           
Now let's go the other way,     
let's have a broadcast.         
So I'm gonna go over to         
EmojiArt, and what I'm gonna    
do is every where I was         
doing my delegation,            
I'm going to use notification   
instead. So let's first review  
what I did after last lecture   
to implement delegation.        
All right, now, just like       
UIScrollView, UITableView,      
etc, I had to add               
a protocol for delegation.      
Now my delegation               
protocol it's called            
EmojiArtViewDelegate only has   
one function in it which is     
emojiArtViewChanged. Of course  
ScrollView has a whole bunch    
of them. DidScroll, view for    
zooming at, table views         
delegate has a lot of things.   
Height of row at, all these     
other things. We only have      
one, just this one. Now notice  
I made this restricted to only  
being implemented by classes.   
Why did I do that? Because      
the delegate method, or var,    
the delegate var in my view, I  
wanted it to be weak. And for   
it to be weak, it has to        
be able to be in the heap,      
and then get released and       
set to nil, when no one else    
is interested in it. Why did I  
make that weak? Well, imagine   
here that my controller sets    
itself as the delegate, which   
is likely. Very, very likely.   
If that happened,               
now we'd have a memory cycle    
because my view would be        
pointing to the controller.     
And of course, the controller   
points to all of its view.      
So now they are pointing        
to each other.                  
They are going to keep          
each other in the heap.         
By making this delegate weak,   
it makes so                     
that's no longer                
going to happen.                
So there's not a memory cycle   
because the view is not         
keeping the controller in       
memory cuz this is a weak       
pointer to it. So I added       
this var, this weak var, so     
now anybody who wants to know   
if I've changed can just set    
themselves as the delegate and  
of course the controller is     
going to do that. Then, every   
time I changed like right down  
here. I just sent this message  
to my delegate if I have one.   
My delegate could be nil, I     
don't have to have a delegate.  
And I just send it and          
of course I'm the sender,       
right? Delegate methods, we     
all will send ourselves along   
as the first argument. Do you   
know? You've noticed that       
I'm sure with ScrollView and    
TabelView and collection.       
They always send themselves,    
it's just convenience sake so   
that you have it right there.   
So I do that as well. Now       
this is not the only change,    
this is one I'm dropping.       
Of course, if I drop a new      
emoji in, that's a change, but  
I also had to go over here to   
gestures. And this is what      
I was talking about before,     
it's kind of annoying           
like when I select and move     
a view. I had to say, well,     
if this is the end of this      
gesture then send it.           
And also down here where I      
resized. I had to go and say,   
well, if it's the end           
of resizing, send it.           
Now I want to get               
rid of these and                
I'm going to be able to with    
KVO, but we'll leave them in    
there for now. So that's        
delegation. That's all that's   
necessary on this view side.    
Then on the controller side,    
what I did was when I created   
my emojiArtView down here,      
I set myself as its delegate.   
Well, if I'm gonna              
be its delegate,                
that means I have to implement  
the EmojiArtViewDelegate just   
like those implementing         
scrollviews delegate.           
And that means I have to        
actually implement that which   
is right here in my             
emojiArtViewDelegate methods    
implemented, and what did I     
do? I called documentChanged,   
and what is document changed?   
Here is document changed,       
it's the method                 
formerly known as Save.         
Cuz I ditched my Save           
button when I did this and      
just called and Save. These     
contents up here is exactly     
the same as it used to be.      
Just update my documents        
model to be my model and then   
update the documents changed    
count. It's all I do here.      
So that's delegation,           
that's the entirety of it.      
You see how it all works?       
Quite simple, and               
we're not gonna,                
we're not use delegation        
anymore in this.                
We're gonna leave               
delegation in the view but      
we're not gonna use             
it in our controller.           
Instead, we're gonna            
use a radio station.            
So let's go back                
to our artview and              
broadcast on a radio station.   
And I'm just gonna do           
it everywhere where I was       
talking to my delegate.         
Instead, I'm gonna broadcast    
on a radio station.             
I'm just gonna say              
NotificationCenter.default.p-   
ost, that's how we broadcast.   
And I have to give it a name    
and who is broadcasting. Well,  
who is broadcasting is me,      
and what are we gonna do for    
a name? Well, as I suggested,   
I recommend going here and      
doing an extension to           
notification.name and           
add your own static let         
which I'll call EmojiArtView    
did change notification and     
set it equal to                 
a notification.name with any    
string you want in here.        
I'll probably just use          
the same string here.           
It doesn't have to be the same  
string but I will, and          
this will now make it so        
you can do                      
notification.name.emojiartvie-  
wdidchange. That's the name     
of our radio station.           
Remember radio stations         
are Notification.Names, so      
this is that. So now,           
I can go down here and          
say I want my name to be        
Notification.Name.EmojiArtVie-  
wDidChange. And by the way, of  
course, Swift can infer this.   
So we can just go like that,    
which is what we would do, and  
type all of that in             
Notification.Name stuff for     
no good reason. And this is     
it, so that's all we need to    
do is do this. Now of course,   
we need to do it here,          
but we have to go again         
over to gestures over here.     
And do it in the same place we  
do this delegate right here,,   
where's this other              
one up here?                    
Okay so, again,                 
that's kind of annoying,        
we'll fix that with KVO. But    
right now, we're broadcasting   
on this radio station every     
time something changes.         
We resize something, we drop    
something, and whatever.        
Now, back over here             
in our controller,              
I'm no longer going             
to be a delegate.               
So I'm gonna go down here and   
just get rid of all this.       
So I'm not longer gonna set     
myself as the delegate here.    
Get rid of this entirely,       
I'm no longer gonna implement   
the EmojiArtView delegate. I'm  
no longer going to say that     
I implement                     
the EmojiartView delegate.      
So, now I've disconnected       
myself from my view.            
So instead, I'm gonna listen    
to that radio station, so       
where am I gonna do that? That  
one, let's start listening      
once the document's open.       
Until the document's open it's  
gonna be useless to listen to   
my emojiArtview. So again,      
I'm gonna need another          
little observer guy here.       
So I'm gonna call this one      
my emojiArtviewObserver cuz     
that's what its gonna be        
observing, the emojiArtview.    
I'm gonna say                   
emojiArtViewObserver, go,       
'm inside a closure here, cuz   
this is the completion closure  
of opening. So I'm gonna say    
self.emojiArtViewObserver       
= NotificationCenter,           
that's how we listen.           
Default.addObserver, same       
way as we add observer for      
the UIDocumentState.            
Let's sort this out again,      
so we can see this all real     
clearly. All right, so          
the name is                     
notification.Name.EmojiArtVie-  
wDidChange. And again,          
we don't need that just I was   
doing that so we would see      
it clearly. The object is my    
EmojiArtView, that's the only   
one I'm interested in hearing   
about emojiArt,                 
you did change broadcast.       
The Queue, of course operation  
Queue.Mean because I'm just,    
although surprisingly this      
would not need to be on main.   
Because all I'm gonna           
do is tell my document,         
which is part of my model,      
extended part of my model.      
I'm just gonna tell that it     
changed. That's not anything    
UI, so I don't necessarily      
have to do that here. I could   
put nil here and be pretty      
safe no matter what thread I'm  
broadcasting on. Now I happen   
to know that my emojiArtView    
is broadcasting from the main   
thread, right? Because it did   
it when it dropped or           
when someone resized, clearly,  
I'm on the main queue there.    
So it wouldn't matter but,      
anyway. Okay so here we go,     
now we do get this              
notification. Turns out that    
our EmojiArtView does not play  
any music when it broadcasts.   
It could, it could maybe send   
you the label that it added or  
changed or something.           
But it doesn't, that's okay.    
We don't care, because all we   
wanna know is that something    
changed so we can say           
documentChanged, right? That's  
it, now, of course, we need     
to stop listening to this.      
When is a good                  
time to do that?                
I'm gonna do that               
when you hit close.             
And I'm gonna do it whether or  
not you successfully closed     
because I'm gonna               
get dismissed. So               
I'm gonna most definitely       
stop listening here.            
And I'm just gonna say          
if I can let observer,          
observer = my emojiArt.View     
observer, art view observer.    
Then I'm gonna ask              
the notification center,        
the default one,                
to remove that observer. And    
that's it, so this is quite     
a bit simpler than delegation,  
on both sides. I's              
a little easier to do this.     
You don't have to implement     
that another method.            
You don't have to set           
yourself to delegate.           
You do't have to do that.       
You just start listening and    
stop listening and              
you're going to find out. So    
that's why we use notification  
a lot of times in place         
where other times we've used    
delegation and it's true        
in other classes, as well.      
All right, so let's go see if   
we broke anything. Cross our    
fingers that removing           
delegation entirely from our    
mode emoji.Art.ViewController   
did not break anything.         
And luckily, we have that       
other observing going on, so    
we'll be able to tell.          
So here's apple bee,            
let's bring up our Console      
there, change to normal,        
that's good. Now, hopefully     
when we drop something in,      
hopefully, that caused          
the radio station broadcast to  
happen so that we notice        
something is different.         
And hopefully, this is going    
to auto save in a moment,       
and we can force the issue      
by threatening to               
go somewhere else. Woo, it      
did it. So, it must have been   
that our radio station worked.  
And we noticed that change,     
otherwise we wouldn't have      
auto saved there. Okay          
the last thing we're gonna do   
is use KVO to rip out some of   
that code that's calling the    
delegate and posting down in    
my gesture view. Basically      
what I wanna do is go           
to my gestures right here,      
and I wanna remove this code.   
See, this is the code where     
I'm telling my delegate and     
posting on the radio            
station when, in this case,     
something moved.                
So I want that out of there,    
and then down here for resize,  
this is when we resize,         
I want this out of there.       
So I'm just gonna delete that.  
But I obviously, still need     
to tell people when I change.   
So I'm gonna go back to my      
ArtView here. And as soon as I  
add a label, I'm going to have  
that label be observed for      
its center changing. And if     
its center changes, I'm going   
to notify my delegate and       
broadcast on my radio station.  
'm basically gonna              
do this right here.             
So how do we do that? The       
trickiest thing about, this,    
it's actually quite easy.       
We're just gonna to label       
observe, and                    
what property observing /.      
Center.                         
And when we observe, we get     
a closure. The closure's gonna  
pass the label back to us, and  
that little changed object,     
right there. And we can do      
whatever we want in here.       
And what do we want to do?      
We want to do this.             
Tell our delegate and tell      
the radio station something     
changed. But remember observed  
returns a cookie. And           
we have to keep that cookie in  
the heap as long as we want     
this to happen. So I'm gonna    
do that by having a little      
private var which I'm gonna     
call my labelObservations.      
Which is gonna be a dictionary  
with UIViews as the keys and    
these NSKeyValueObservations    
as the values. Now putting      
things in this dictionary is    
gonna keep things in the heap.  
But only as long as this        
EmojiArtView is in the heap.    
As soon as this EmojiArtView    
leaves the heap                 
this will leave the heap and    
all the observations            
will leave the heap, woo-hoo.   
So that's what's great about    
this, not having to do          
that remote observe,            
remove observer thing like you  
do with notifications. Because  
when things leave the heap      
naturally the observations      
naturally stop. However, what   
if we don't leave the heap and  
we remove that subview.         
We don't have any,              
actually have any UI            
to remove our emojis.           
They once they're in there,     
they're there forever. But      
we could imagine putting some   
sort of gesture that would      
remove them, so we wanna        
anticipate that day and         
I wanna make sure we remove     
it. So, first of all let's put  
the observation,                
KeyValueObservations in here.   
I'm gonna say                   
labelObservations               
sub the label =                 
this observation.               
So this the labelObservation    
for this label, right. Now I    
have to whenever this view      
gets removed from super view,   
I have to let this              
observation leave the heap.     
In other words, I will have     
to remove it from here.         
Everyone understand that?       
So how do I do that?            
Well, luckily, there is         
a nice method in view called    
willRemoveSubview.              
And of course,                  
we're gonna call                
super.willRemoveSubview. And    
this gets called anytime        
a view gets removed from me,    
which is perfect. All I'm       
gonna say here is I'm just      
gonna check to make sure that   
this view that's being removed  
is actually in the              
labelObservation tier. So I'm   
gonna say if LabelObservations  
subview does not equal nil,     
in other words it will have     
an observation for it.          
Then I'm gonna set              
the labelObservation for        
that subview to nil.            
Boom, it just left the heap.    
As soon as I clear that thing   
out of this it went away.       
It stops observing which        
is exactly what I want,         
everyone got that?              
So that's all we need           
to do to do this.               
Let's make sure we didn't       
break anything here. Okay so    
we got our Apple Bees right     
here. Let's change something.   
Okay let's take this eight      
ball and move it over here.     
And then let's try and          
threaten,                       
oops let's get our console      
up here. [INAUDIBLE] here,      
okay let's threaten             
to go somewhere else.           
Woo-hoo, it auto saved!         
It worked again. All right,     
sound good?                     
Back to our slides.             
Good timing here.               
Now you remember                
we talked about the view        
controller lifecycle right?     
View will appear, view did      
appear, all these things.       
Well the same kind of thing     
happens with your application   
and it kind of goes through     
this chart up here.             
So, I'm going to talk about     
how it transitions through      
all these stages, but           
first I'm going to talk about   
the stages. So first of all     
there is Foreground Inactive    
and that is where your code is  
running, but you're not         
getting any UI events. So you   
can't do anything. So you can   
only do kind of preparation     
work in this space. Then        
there's Foreground Active.      
This is the normal              
state you're used to.           
Getting UI events, view         
controllers coming on screen,   
segueing, you're                
doing all your stuff.           
This is the normal running      
state of your app.              
Then there's Background.        
In the background your code is  
running, you are not            
getting any UI events,          
you never live here for long,   
maybe 30 seconds. So this is    
transitory state, so anything   
you do in the background state  
you gotta do it fast. And       
then you go into this state     
Suspended. Here your code is    
not running. It's important     
to understand no code in your   
app anywhere runs. Your app is  
not getting any CPU cycles.     
Now what's important            
about this state is that        
you could be killed at anytime  
in this state. All right,       
so let's talk about how         
we transition here. One         
transition is launching your    
app. So when you launch your    
app, you go from not running    
where your binary is not even   
executing, to briefly,          
the foreground inactive state,  
and the foreground active       
state. So you do pass through   
that foreground inactive state  
briefly on your way to running  
when you launch. Now, another   
important one is when you       
switch to another application,  
right?                          
So you're the active app,       
someone's using you, and        
then they switch                
to another app.                 
And when that happens, you go   
up to Foreground Inactive for   
just a moment, and then all     
the way down to Background,     
you sit in the Background for   
maybe 30 seconds, and           
then you move to Suspended.     
And                             
now from Suspended either       
you get reactivated,            
if they come back to you, or    
you get killed at some point.   
Those are transitories.         
When you get killed,            
you go directly from            
Suspended to Not running.       
You don't pass through some     
state where you get to run any  
code. Let's talk about          
how you get notified for        
all of these transitions.       
What happens and what           
you're supposed to do. Now,     
all of these things             
I'm going to tell you,          
by the way, not really that     
important. Because a lot of     
things are taken care of for    
you. For example, UIDocument,   
you notice how when we          
threaten to go to another app,  
it autosaved. It knows about    
these transitions. It's doing   
that for you, so you don't      
even need to do anything.       
And that's true of a lot        
of things in iOS. So            
I'm gonna show you              
all of these things.            
And the way you do it,          
but most of the time,           
you don't even need to do       
anything. You just need to      
know that these                 
transitions are happening.      
All right, so the first         
transition is from Not running  
into this Inactive state,       
this Foreground Inactive.       
This is kinda like preparing    
your app. When this happens,    
like all the things that        
happen here that I'm gonna      
talk about, a method in your    
AppDelegate.swift, you know     
that stepchild that we keep     
foisting off into supporting    
files. Actually we did look at  
it last time. Remember it had   
the thing where you're          
opening the URL? Remember we    
had that little code in there   
that we were talking about,     
that UI document browser view   
controller, handles opening     
the URL for us? So              
we have looked in there. But    
there's a lot of                
methods in there.               
And that's what all of these    
transitions have is they call   
methods in there. And you'll    
see there's stubs in there.     
If you go look at it there's    
stubs in there, that have       
commented out stuff that        
kinda tell you about them.      
So this is all pretty           
well documented in there.       
By the way,                     
all of these transitions also   
are broadcast on                
radio stations. So              
you can just sign up and        
put a closure and               
want this transition            
to happen,                      
a closure could be executed,    
all right? So that's important  
to know as well. Not so useful  
for the very first one which    
is application will finish      
launching with options.         
And application did finish      
launching with application,     
cuz that's one of the first     
time you actually write your    
own code. And notice that that  
thing has a little dictionary   
passed in, right? Application   
will and did finish             
launching with options.         
That dictionary tells you       
why you were launched. Now,     
why would you be launched?      
Well, of course the user might  
have touched on your icon.      
That's most of the time.        
But you can also get launched   
because someone wants           
you to open a document.         
We're EmojiArt, and             
someone wants us to open        
an EmojiArt document and        
we're not running, we could     
get launched to do that. You    
can also set up things where    
you get launched when the user  
walks by a dry cleaner.         
You can actually register       
a Place in the world and walk   
by, boom, you'll get launched.  
You can also have this          
activity continuation thing,    
where you're working in         
emoji art on your iPad,         
and then you switch             
over to your iPhone.            
And then in the corner there's  
a little icon you press.        
Now you're right back in        
emoji art where you were.       
Well that might have to         
launch you. You might get       
a push notification. You're     
using Cloud Kit, something in   
your database changed, you get  
woken up to say, hey, look,     
you got a push                  
notification for you. So        
there's a lot of reasons you    
get woken up, and launched,     
and that dictionary will        
contain all the information     
you need to know about why. It  
used to be that an application  
will and did finish launching.  
We built our UI.                
We created a split view. We     
created a navigation control.   
We put a view controller.       
We never do that anymore.       
I only mention this because,    
your final project,             
you're gonna go out and Google  
things and look Internet. And   
you're gonna see people say,    
go create a split view in your  
ApplicationDidFinishLaunching   
with options. No,               
we don't do that. Storyboards,  
that's how we do it.            
Those answers were              
pre storyboard. Or              
someone who never got the       
storyboard story. We build our  
UI in storyboards, not in       
these method, in this method.   
All right, the next transition  
is actually coming to           
that inactive state             
from the other side.            
You were the active app, and    
not you're not gonna            
be the active app.              
Probably because the user       
clicked on another app.         
This one is                     
ApplicationWillResignActive,    
because that's                  
what's happening.               
Here you wanna think of         
this as a the pause button.     
You wanna pause whatever is     
happening in your app right     
here. So let's say I use the    
example of an Asteroids game.   
Your shooting Asteroids. You    
want the whole Asteroid field   
to pause when you get this.     
And then the next one           
here is a inactive to active,   
that, unpause.                  
So this is                      
ApplicationDidBecomeActive. So  
you kinda wanna have a pause,   
unpause thing here. Now,        
with a lot of apps, it doesn't  
make sense. You never pause or  
unpause. They're not that       
kinda app. They, they just      
are what they are, so           
you don't have to do anything.  
But if you have an app where    
things would make sense         
to pause, this is where you     
pause and unpause in these two  
things. Now, this one,          
right here, is, someone         
clicked on another app, you've  
gone through active, inactive,  
now you're going around         
to this background state.       
This is                         
ApplicationDidEnterBackground.  
It's time right here to         
batten down the hatches.        
Close your files, get yourself  
in a situation where you could  
be killed. You've got about 30  
seconds here to prepare to be   
killed.                         
You might not be killed,        
but you might be. So you wanna  
not have any files open,        
that are gonna get corrupted    
if they get closed, or          
an unsaved data in your app,    
close things up here. and       
you get 30 seconds to do it.    
You can ask for an extension,   
short extensions of time,       
but if you ask too much,        
the system will stop granting   
you those exceptions,           
extensions.                     
So pretty much think about,     
you've got 30 seconds or so     
to get your hatches battened    
here. The next one here is      
applicationwillEnterForegro-    
und.                            
So here, you went down          
the background view,            
you battened down the hatches,  
and you got activated again.    
You didn't get killed.          
Here you wanna un-batten down   
the hatches. Open back up the   
things that you had closed.     
Now, a lot of times you don't   
need to do anything here,       
because you're opening up       
things that you closed          
in the battening down           
the hatches, on demand anyway.  
If you tried to                 
access a file and               
it's not open, well,            
you'll just open it then. So,   
oftentimes you don't have       
to do anything here, and        
I kinda recommend writing your  
code in that way. So that you   
don't really ever have to       
un-batten down the hatches. So  
that's, all the things          
that happen.                    
And of all those things you     
get radio station, all those    
things that have methods in     
the app delegates you can do.   
But the AppDelegate does some   
other things as well in there.  
For example, the opening        
URL thing we saw last time,     
it also can do                  
background fetching.            
Which is kind of cool.          
Let's say you have              
a Twitter client, or            
something like that, and when   
someone launches your app,      
you wanna show them             
the latest Tweets. Well,        
you can actually say to your    
app to fetch the latest Tweets  
in the background, even when    
your app is not running. And    
what'll happen is, it'll get    
launched, but it won't come on  
screen, and you'll be in        
that background state for       
a little, little bit of time,   
where you're allowed to make a  
couple of network requests for  
your 30 seconds or whatever.    
And then you go back to sleep.  
So, you can do that with        
AppDelegate. It also manages    
data protection. I don't        
know if you know this but,      
when your device is locked in   
the lock screen, apps cannot    
see the data. It's encrypted.   
It is fully encrypted, so you,  
the apps couldn't do            
anything if they wanted to.     
So, the AppDelegate will tell   
you what's going on about       
when you can access the files,  
things like that. There's also  
a UIApplication, which the      
AppDelegate is delegate of.     
We never subclassed             
UIApplication,                  
we use the AppDelegate to       
configure it's functionality.   
However, UIApplication does     
have a few interesting things.  
Like, it has a method so you    
can open a URL in another app.  
So, your image gallery, and     
maybe you asked to open         
an emoji art document. You      
can ask using that open URL.    
Here's where you register for   
push notifications.             
So, this is something you       
have to do if you want that     
Cloud Kit thing to notify you.  
You have to register for        
push notifications there. You   
can set the fetch interval for  
that background fetching        
I talked about.                 
Here's where you ask for        
more time, if you're in         
the background mode, and        
you need a little bit           
more time to finish up. That's  
happening in UI application.    
The little spinner in the top   
left of your device that says   
there's network activity,       
that's controlled with this     
bool.                           
Unfortunately it's a bool.      
So if you have multiple         
threads acting as a network,    
they gotta share this bool,     
it's kind of annoying,          
but. And you can also           
find out about things,          
like how much time do I have    
left to run in the background?  
What is that preferred content  
size category, you know,        
the slider for the font size?   
What state am I in?             
Am I in the foreground,         
the background, where am I?     
You can find all those things   
out with UIApplication. All     
right, quickly Info.plist, we   
already saw Info.plist in your  
homework. You used it to add    
that app transport security,    
right? You can actually         
edit this directly in XML,      
you just right click on it and  
switch to sources XML,          
you can do that.                
will get a snippet of XML from  
somebody that does something,   
enables something in plist,     
and you're gonna paste it in    
here. But usually we don't      
even edit the plist thing       
directly like we do with        
App Transport Security.         
We edit it in                   
the project settings,           
like we did with                
the document types, right?      
The document types we had for   
Emoji Art View, and for         
your image gallery. We edited   
that all in project settings.   
And the project settings is     
mostly editing the Info.plist   
indirectly. And finally,        
we have the capabilities.       
We talked about this            
with Cloud Kit.                 
There are certain things,       
that to use them you            
have to turn them on. This      
capabilities tab inside of      
your project                    
settings like this.             
Some of these things require    
servers, like Apple Pay,        
and iCloud, and Game Center.    
Some don't, like Maps, and      
Inner App Audio, Home Kit,      
none of those do.               
The things that require         
a server, you can only turn     
these on if you are a member    
of an Apple developer program.  
That costs $99 a year. And      
you can kinda see why that is,  
because to access these server  
technologies, they're kinda     
needs to be stuff in that       
server that knows about you,    
and this providing stuff.       
Well,                           
somebody's got, they gotta      
know who you are for real.      
You can't just be some          
random Apple ID out there.      
You wanna be registered         
in the program.                 
And the $99 seems to me to be   
mostly an administrative fee.   
That's not very much money for  
the amount of functionality     
that you're getting             
with all these servers,         
push notifications, all these   
things. It's all covered in     
one $99 per year fee. I don't   
have time to cover all these,   
but this is a great place       
to go look for interesting,     
not covered in lecture things   
to do. Go look through this     
list and see if you can find    
something fun to do in there.   
All right, that is it.          
On Wednesday,                   
we're gonna talk about super    
important topic, and I, this    
is the last topic I cover,      
really, before you launch into  
your final projects this week,  
which is segues.                
We know about show segues, and  
show detail segues, right?      
The navigation controller and   
the split view controller.      
And we know about modal         
segues too, a little bit.       
We put put up our emoji         
art document modally. But       
we're gonna learn pop over      
segue's, more than just for     
alerts, but pop over            
segue's in general. Also,       
unwinding segue's, and embed    
segue's, two kind of under      
appreciated segue's that you    
can do that are kind of cool.   
We're gonna learn all about     
that, and I'll be demoing it    
all on Wednesday as well.       
Next week is Thanksgiving.      
So, you get a week off.         
That will be great, and         
then we'll back at it           
the week after. All right,      
see you on Wednesday.           
>> For                          
more, please visit              
us at stanford.edu.             
