B1 Intermediate 3279 Folder Collection
After playing the video, you can click or select the word to look it up in the dictionary.
Report Subtitle Errors
Stanford University.
Okay, well, welcome to lecture 7 of CS193P.
This is the winter of 2015.
And today,
we are going to talk about multiple MVCs, all right?
That includes split view controller,
navigation controller.
We talked about tab bar controller a little bit
last time.
We're also gonna talk about segues which is how we make
all those multiple MVCs kind of transition to each other.
And I have a big demo that shows it all off.
And that after that demo I'll come back.
We'll talk about popovers which are similar thing for
having multiple MVCs but are not quite the same.
So that's why I've kind of
segregated them off to the end.
And we'll have a demo about that.
All right. So MVCs working together.
These are the slide we saw at the end of last time.
We're trying to build apps by taking our MVCs and combining
them with tab bar, split view, and navigation controller.
We talked about tab bar controller which is
just simply four or five or however many
MVCs all connected by just having this little tab bar so
the bottom just picks which MVC you want to see.
Each MVC by the way in the tab bar's completely independent.
It runs on its own.
It doesn't depend on the other ones.
It actually might be kind of bad object on your
programming really for them to depend on the other one.
So, tab bars for peers that aren't really talking to each
other they're just working together, they're related.
Maybe they share a model and
they're each having a different part of the model
or whatever.
And then we talked about split view controller,
which only has two MVCs in it, a master, and a detail.
We call them master and detail, by the way,
because the master is usually the one determining what's in
the detail.
So the master is letting you view something,
and then you're going to use the detail to see more detail
about what you're doing in the master, okay?
So that's why we call it master and detail.
So we're going to pick up now with navigation controller.
So navigation controller is just yet another MVC whose
view is multiple of other MVCs and navigation controller can
handle any number of other MVCs.
And it puts them on screen, it shares the screen instead of
just putting them side by side or putting them with the tabs,
it puts them like a stack of cards.
So NavigationController's basically stacking them
like cards and you can only see the one on top.
That's how NavigationController
shares the small screen space between multiple MVCs.
So it's gonna stack these MVCs up.
So here's a NavigationController.
And it's got an MVC in it.
This is the All Settings MVC from your device.
If you go look in your iPhone or
whatever, you'll see the settings app looks like this.
So this is just an MVC that's kind of the top level.
Has all the settings accessible from here.
Now the navigation controller is drawing only a little part
of it's view here, which is that title bar.
And the navigational controller will put the title
there, and also you can have a couple of buttons up at
the top and the navigational controller draws that part.
The rest of it is totally drawn,
and even underneath that title bar, totally drawn by
whatever MVC is on top of this stack of cards.
Okay, and right now the only thing on
our stack of cards is this All Settings MVC.
Now even though the contents of
the top are drawn by the navigation controller, what
the contents are is determined by the MVC that's showing.
Okay? And that's done with this
UIViewController property called navigationItem.
So if you go look in the documentation for
UIViewController you'll see this property navigationItem.
If you click through to the type UINavigation item you'll
see that it's got a lot of properties and
they're like left button, right button, title.
Things like that. So,
the way the navigation controllers figures out
what to put in the top bar is it asks whatever MVC is on
top of the stack.
So as you go to different MVCs being on this stack of
cards that thing at the top will change.
So, let's say I click on General here,
because I want to see general settings.
Okay, so I click on it, and a new MVC gets put on top of
the stack of cards, so now I can't see the other one, okay?
This new one is overlaying it,
and this is just a general settings MVC.
Completely different MVC,
completely independent of the other one working on its own.
By the way,
I don't have a good screenshot of this unfortunately, but
it's also possible for the navigation controller to
draw some buttons along the bottom there.
A little small sliver on the bottom.
And it get those button items to put there,
by asking the MVC that's on top of the stack of cards for
the toolbar items property.
So if you look at toolbar items,
it's just an array of these bar buttons, so
any MVC that returns anything in that array,
when it's in a navigation controller like this,
those buttons will appear at the bottom.
So those would change each time you go
to the next thing on the stack as well.
So let's go ahead and click on something here.
Let's click on, oh sorry, the back button.
Yeah, you see there's a back button in the upper left.
The back button says, Throw the top card off.
That's basically what back means.
Throw the top card on
this stack of MVCs that we're building, throw it off, and
then I'm going to go back to where I was before.
So that's how back works, it just throws it off.
And when it throws it off, it completely throws it off,
it disappears.
Completely gone.
All right?
Out of the heep, okay?
All right, so let's put another card on the stacks,
I'm going to click on accessibility here,
another card's going to slide in,
I'm trying to simulate the animation of it but in keynote
I can't exactly do it, but it slides in from the side.
And this is yet
another completely different MVC, the accessibility MVC.
And we can pick something out of here,
like I'm going to pick larger text right there, and
another MVC is going to slide in.
So we have four MVCs, totally different MVCs,
on our stack of cards right here.
And the one on top, which is the last one that I chose,
this larger text MVC, is showing.
Okay? The rest of them are there,
you just can't see
them because they're underneath this top card.
Okay, so now let's do the back button.
So I'm going to click this back button in the upper left
and when I do, it takes that larger text one off, throws it
out, and now we've got the accessibility card, which is
now the top of our stack which only has three things on it.
And we can do back again.
It goes back to the general one.
We do back again.
It goes back to the very top.
Of course, once we get back to the very top there's no
more back button because this is the only card on the stack.
Okay, so everyone understand what
a NavigationController is?
It's just a stack of MVCs.
All right?
But it's just like split view controller and
UITabBar Controller in that it is showing multiple MVCs.
So I'm going talk a little bit about how navigation
controller works internally, so you can get a feel for it.
And I'm going to try to mix it with our MVC image that we
had so you can kind of combine the two concepts in your mind.
So, let's say I had an MVC.
This one up here, the purple MVC thing.
And I had more features I wanted to put on there, but
there's just not enough room on the screen anymore,
I've kind of maxed out.
Or it's just those features don't logically make sense to
be in the same place.
Well, what I would do is create another MVC to manage
those other features that won't fit,okay?
And, so now though I need a way to have those two MVCs
share the screen and I can use a split view controller or
tab bar controller if they were peers or
I could use navigation controller.
So, let's see what it would look like to
use a navigation controller to have these two MVCs which
they're related share the screen.
So a navigation controller is just an MVC, okay?
It's a controller of an MVC.
And it's view is a little rectangular area that usually
fills the entire screen or a portion of the screen.
It's got the title.
But it's a special MVC and they've just got an outlet
called Root View Controller that points to an MVC.
[UUU] points to the controller of an MVC.
And when it is pointing to that, then the navigation
controller puts that MVC's view, okay, its view property.
All right, we know that UIVController has
this very important property called view,
which is its top level of its view.
It puts that on the screen underneath this title thing.
So it fills the entire rectangular area and
then the title kind of overlaps it transparently,
semi-lucent transparency.
So that's great.
So we got it in there.
Now how do we get the other MVC on?
Well, when a ui element inside the view of
this MVC like a button or something like that
is pressed then it can cause another MVC to get created.
You notice that MVC just appeared?
It wasn't there before.
But as soon as the button gets pressed in this guy's view,
this MVC's view, that thing gets created.
And that's something important to notice that we're always
going to be creating a new MVC when we do these transitions.
Okay? Transitioning to a new card.
In a split view,
we do something in the master that changes the detail.
That's always creating a new,
even the first time we press a tab bar, but
only the first time for the tab bar, it creates a new MVC.
Okay? So it creates this new MVC.
And then the NavigationController just
moves over to put that MVC's view on top.
All right?
And then of course you've got the back button.
When you click the back button,
it goes back to the first MVC.
And look what happens to that MVC.
That is not hidden or something.
It's just gone.
It got de-allocated probably from the heat.
Okay? And then we're back to here.
Okay, so that's how navigation controller works.
Very simple.
And, you know, split view and
tab bar are similar kind of mechanism.
Okay. So
how do we get at these sub-MVCs?
So let's say I had a split view controller or
a navigation controller or a tab bar controller.
How do I get at the things on the stack of cards,
or the two things the master and detail?
And the answer is
they all have a property called view controllers.
And it's an array of view controller.
And that it's all the view controllers in a system.
So in a split view, there will be only two in there,
the master and the detail, in the tab bar there will be how
ever many tabs there are, in a navigation controller there
will be however many cards are on the stack.
That's how many things will be in that array.
And it's settable too which is a little weird,
we don't usually set things but you can do it.
And the way we usually set it is we're going to
do it in the story boards or navigation controller for
example has methods like push and pop view controller that
will push view controller onto the stack.
But that is doing that in code and
we are usually doing all of this stuff in story boards.
So that's how you get at the sub things of
these three kinds of view controllers.
What about, how do I get a hold of the view controller?
Okay? How do I get that
navigation controller?
How do I get a pointer to it, or whatever?
Well it turns out every view controller knows if it's
inside a navigation controller or if it's inside a split-view
controller, or if it's inside a tab bar controller.
It knows.
And so UI view controller has these three properties: tab
bar controller, split view controller,
navigation controller.
And they will return to you the split view
controller that the view controller is in.
If it's in one, if it's not then it returns nil.
And notice some view controllers might be inside a
navigation controller, inside a split view controller.
So more than one of these things can be
non-nil at a time.
Because we can nest these things to build more powerful
user interfaces.
So let's just use the example, if I'm the master in
a split view, and I want to get the detail.
Well I can get the split view controller I'm in by
saying split view controller.
I'll put the little question mark there,
that's optional chaining.
If it's nil,
then I'm obviously not going to get my detail.
And then I'm going to say view controller sub 1,
because we know that view controller sub 1 in
split controller is the detail.
So now I've got the detail and
I can talk to it I could, you know, get to my detail.
So presumably I might want to tell it to
do things display things or whatever, okay?
So that's how we get at these things in code if we need to,
but we often don't need to because we can manage most of
this in the story board.
And so how do we wire this up, how do we create this
relationship between these split through tab bar and
navigation controller and these all the sub-MVCs.
And it can be done in code, okay?
But we're gonna do it
in storyboards in this class all the time.
Okay. And we're just
gonna use Ctrl + drag to do it.
So let's see what that looks like.
I'll do it for split view controller,
we're just going to go the utilities area,
the same place we drag out a button or something like that.
We're going to drag out a split view controller.
Now, when it comes out,
it's going to come out with a whole bunch of other MVCs
pre-attached to it in attempt to help you, but
usually you're just going to delete those so
that all you have left is the split view controller itself.
And then you're going to Ctrl+Drag from the split view
controller to the master and
Ctrl+Drag from the split view controller to the detail.
And that's how you are going to do the wire.
So this is what it looks like.
Here I have a storyboard.
I've dragged out of split view controller.
That's that gray thing on the left.
I deleted all the things it was attached to so
I just had that.
Then I Ctrl+Drag to,
in this case my master, which is my calculator.
When I do that, it's going to put up this little thing says
okay, what kind of connection do you want to make?
And you're going to pick master view controller there.
And that's going to make like a little connection to it.
And then I'm going to Ctrl+Drag down to my detail,
which is going to be the right side of my split view.
And here I'm going to choose I want Detailed View Controller.
And then I'm going to have this,
fully hooked up split view.
And that's it.
So it's very easy to hook these things up.
All right, and tab bar,
you can hook up exactly the same way.
Connect as many of them as you want, okay?
Navigation controllers can be done a little bit differently,
which we'll see in a second, okay?
But there's a problem here which is that a split view
can't display side by side on an iPhone.
Or at least not anything but an iPhone 6 plus.
That's the only one big enough to really display side
by side.
So a split view really can't work on an iPhone.
The way we handle this is that iOS adapts its
user interface to whatever device it happens to be on,
depending on how its size class is.
We'll talk about size classes later, but if it's compact,
like a phone, then it can't show it in a split view.
So how can I show it then?
If I have it master in a detail and
I wanna show it on an iPhone the way I show it is with
a navigation controller.
So instead of having master and
detail on the screen at the same time on an iPad,
on the phone when I click in the master, same button that I
clicked to make the detail show it in split view,
but when I click in the master on the iPhone is going to
slide the detail on as a card.
On the deck.
All right.
On the navigation charts stack.
Now the thing is though we want to
build one storyboard that will work for
both platforms and automatically adapts.
So how do we do that?
We're just going to wrap our master in
a navigation controller.
So here is a Navigation Controller,
which is my master, it's the calculator, right?
And you can see it's hooked up to the split view already, and
I'm just gonna select it, and then I'm gonna go to
the Editor menu and pick Embed in Navigation Controller.
See that embed?
And this is what's gonna happen.
Okay, the Navigation Controller,
is going to the interposed between the split view and
the master.
So now the master, is in a Navigation Controller.
Now if I am on an iPhone, and I click in something
that would change the detail, then it's going to push it
on that Navigation Controller, on top of the stack.
But if I am on an iPad it's going to
show them side by side.
So this structure that you see right here,
split view, navigation control for
the master and then detail is very common.
A universal way of specifying your UI so
it works on both, okay?
Now we can also put the detail inside of
a Navigational Controller too, why would we want to do that?
Well the only reason we would wanna do that,
is cuz maybe we want
the Navigation Controller's feature of a title, right?
Or little buttons we wanna put at the top.
It's really nice for that.
But, we don't need
a Navigation Controller down there for navigation,
because we are never navigating from the detail.
We only navigate to the detail.
So, it doesn't, itself, need to be in its own
Navigation Controller, and we'll see that in the demo.
All right, so that's how we wire these things up.
Okay, and they end up looking like that.
Now how do we make these things appear?
How do we make changes in our master,
that cause something to appear in the detail.
Or if we have a Navigational Controller that has multiple
cards, when we clicked all those buttons and another card
kept coming on in the stack, how did we do that, okay?
And the answer is we use segues, okay?
So segues is, how these things transition from
view controller to view controller.
There's really four kinds of segues.
There are custom segues, too, but
we're not gonna talk about that in this class,
kind of advanced, you almost never need those.
So there's four basic segues.
There's show segue, okay?
Which basically shows the MVC that you're talking about, and
if you're a Navigation Controller, it will show it
on the, it'll put it on top of the stack of cards.
If you're not in a Navigation Controller,
then it will show it modally.
Okay, so now, modal presentation of an MVC,
we haven't talked about that with all these other things,
but basically it just takes over the entire screen.
Okay? Just completely takes over the
entire screen, puts the MVC that you wanna show on screen.
So it's very kind of disruptive to
the user a little bit, because their app is stuck,
it can only do what this MVC is asking them to do.
So I kind of recommend against using modal, and
trying to keep your apps from doing that.
So if you're using a show segue,
you probably wanna be in a navigation controller, so
that it will slide it on deck.
Because, then the user can always go back,
if they didn't mean that, they can go back.
Then there is show detail segue, very similar to show,
the only difference with show detail is that if
you happen to be in a split view controller it
will show this MVC as the detail, okay?
Otherwise if you are in Navigation Controller, but
not in a split view controller it just pushes it
on the stack just like show would, okay?
So, show detail tiny difference there.
It's just about split view.
So, it really helps you when you're in a split view
decide whether what you want is the master to,
if the master is in a Navigation Controller,
if you want that to slide on the master?
The thing you're segueing to or
do you want it to appear in the detail, okay?
Then there's modal which forces this full
screen takeover type of thing.
I'm not even gonna talk about that, I'll talk about it
later in the quarter, but I don't wanna talk about it
early because it can be used as a crutch to build UIs.
You really wanna be using Navigation Controllers, and
split view controllers to do that.
And then a popover segue.
Now a popover segue pops the view controller that you're
segueing to, up into a little window that's on top of
everything else, but just a little window instead of
taking over the whole screen.
But it, really is taking over the whole screen,
because the user an only interact with what's in
the little popover window, if they click anywhere else,
it dismisses the popover window.
But what makes popover nicer than just modal is that,
since it doesn't take over the whole screen, you can still
kind of see grayed out where you came from, and if you
click where you came from, it puts the popover away.
So the popover has very easy to cancel, it's very easy for
you just to get back to
where they were if they didn't really mean to click that.
Okay, so that's popovers.
So we'll talk over popovers at the end.
Again I wanna emphasize what she was talking about on
the previous slide segues of all kinds,
no matter what you're doing, show detail, modal or popover.
They always create a new MVC.
You're never segueing to an existing MVC anywhere.
You're always creating a new one always,
that's what segues do.
Okay, that takes a little bit of
getting used to in your mind.
Because of course you see this stack of cards.
Navigation one, and you press back.
And then you click to go back to where you were.
And you think you're going back to the same one.
But you're not. Because as soon as
that thing comes off the stack, [SOUND] it's gone.
Even in split view.
You click in the master it updates your detail.
You click again in the master to update the detail,
and the detail changes and you think oh,
that was the same thing it just got changed.
No the previous one got thrown away and
new detail got created, okay?
So segues always created a new MVC.
All right, so how do we make these segues happen, okay?
You can do this in code as well, and
I'm gonna show briefly how you do this in code.
But in 90% of the time you're gonna do it
in a storyboard with control drag,
which is how we create most of the things we do in IOS.
So here's an example of doing it with the control drag,
I'm control dragging from a button in my calculator, so
I added a button.
The icon is very, very small but
it actually looks like a little graph.
So I'm control dragging from that in the upper right corner
there down to the detail, because I
want when that buttons pressed I want the detail to be
replaced with a new graphing MVC, okay?
When I let go it that,
it's gonna say, what kind of segue do you want?
This little black box is gonna appear.
And here I'm gonna pick Show Detail,
because if I'm in a split view,
I wanted to replace the detail.
If I was in a Navigation Controller only,
I probably still would choose Show Detail because that
also pushes on the stack.
But if I were the master in a split view and
I didn't want it to do the detail,
I wanted it to actually slide on the stack of the master,
cuz the master could be a stack then I would use show.
All right?
I could also make it a popover or a model here.
So I'm gonna pick show detail, that's what I want.
And it's gonna make a line appear in the story board.
And the middle of the line is a little round circle.
If you click on that and bring up the attributes and
specter, on the right you'll see that there's a little pop
up that says what kind of segue you want.
We already, we already chose this one to be show detail.
And there's also a critical field there called Identifier.
That's a unique Identifier for
this segue, and you need this Identifier.
Let's talk about, why we need this Identifier?
So I'm gonna call this Identifier for
this own show graph.
And you should usually, call the segue something that
is probably a verb phrase that says what this segue does.
So this segue when you're pressing the button it
shows a graph so I'm gonna call it show graph, okay?
So just type that in there.
So, I told you before that everything in the storyboard
is linked up with what's in your code by name.
Whether it's the class of view controller.
Class of of UI view.
Name of an outlet.
Name of an action.
Name of a segue which is
basically what the Identifier of a segue is.
They're all just names, and
we have to make the names the same in our code.
So it's a loose coupling to make those two
things work together.
So, we'll have to reference this name in our code.
Okay, so where, where are we gonna use that Identifier?
Well, one way we can do it, only the 10% case I said,
is to cause a segue to happen from code.
And you do that with
UIViewController method performSequeWithIdentifier.
And you just specify that Identifier, and
it's gonna make that segue happen, okay?
Simple as that,
as long as they're talking about this one,
because you're not gonna be doing this one,
probably ion this class, maybe in your final project,
you might find a reason to do it.
But the number one reason to have the Identifier in there
and the main thing that it's used for
is to prepare a segue, because when that segue happens,
it creates a new MVC, that new MVC was just born.
It needs to be prepared to do what it wants to do.
So for example,
in the calculator case, when I segue to a graphing MVC,
it's just a blank graphing MVC.
I have to tell it what to graph.
I have to prepare it basically, okay?
So, that's the number one thing, preparing.
So how does preparing work?
Preparing very simple.
The MVC that contains the instigator of this segue.
Like the button, or whatever's causing it to segue.
That MVC implements a method called, prepare for segue.
And inside, it gets the MVC that was just created, and
it has to prepare it.
So let's talk about what that code looks like,
prepare for segue.
It takes two arguments, okay?
The first one is the segue.
That's UI storyboard segue instance and
it really has two important things in there.
One is the Identifier, so
you know which segue you're preparing.
And two is,
the MVC that it just created that you're going to segue to,
which is called the destination view controller.
It has a second argument there,
which is sender, that's just the UI button or
whatever that caused the segue to happen.
You don't usually need to look at that but sometimes.
We'll see later in the quarter when we wanna look at that.
But that's all it is,
it's just what object caused the segue to happen.
So we're gonna look at that segue identifier.
It's just a property, segue.identifier.
It could be nil, because you might not have set it.
And so you wanna check if it's nil here, so
here I am doing if, let to check if that thing is nil.
Then I'm just gonna switch on it, okay?
And I'm gonna look for Show Graph, and
once I know that, but I'm preparing to show a graph,
then I can say, give me the MVC,
that graphing calculator MVC that you just made.
Now, the thing is segue dot destination view controller,
that property is any object.
Okay, so you have to use as to turn it into
the right class of the MVC you just create.
Now in the case here,
I created a calculator graph view controller,
I've abbreviated here calc graph view controller,
although you shouldn't do that in your homework, okay?
It's just that it wouldn't fit on the slide here,
so calculator graph view controllers are on,
turning that destination view
controller into a calculator graph view controller, and
if I can't do it, well then I can't prepare it.
So, I'm just gonna do if let there.
So if I can, then I'm just going to call methods and set
properties in that calculator graph view controller, that
are needed to prepare that thing to come onscreen, okay?
So again in this case I
would probably tell it what I wanted it to graph here.
Okay, maybe I would set it to color, or something else.
The scale, or I don't know whatever we wanted to set here
we can do, okay?
Now, I don't put a lot of red on my slides.
And when I do, you really should pay attention, okay?
Very important thing to understand,
is when you are preparing that newly created MVC,
it's outlets have not been set.
Remember outlets are these
implicitly unwrapped optionals, we are always kind
of expecting them to have been set.
Well, this is one case where that's not true.
When you're preparing your MVC, it's outlets are not yet
set, okay?
That can cause crashers, that can cause you to unexpected
behavior, because you set something in preparing it and
you're expecting something in the view to have been set, but
it didn't happen because the outlet is just not set yet.
So you have to take whatever the preparation is and hold
onto it, and then later on when the outlet does get set,
maybe in the property observer of that outlet, you can load
up the information that you're prepared with here, okay?
I'll see that in the demo.
I've made my demo
intentionally crash because of this.
And we'll go back and look at why that happens, okay?
But this is red, pay attention, you know,
if your segue doesn't work the first time,
it might well be because you're expecting outlets to
be set when your MVC is being prepared, okay?
So that's preparing for a segue.
You can also prevent a segue from happening.
If there's some reason it doesn't make sense for
that segue to happen, you could just disable the button,
but if you didn't wanna disable the button you could
click the button.
And what'll happen here is your UIViewController will be
asked, should I perform this segue with Identifier?
It'll pass you the Identifier and the sender.
And you can just return, false.
And then it won't do that segue.
It won't crash or anything.
It just, you know, touch the button, it does nothing.
'Kay, so you can control your segues kind of
programmatically as well like that.
So, demo time here.
We're gonna demonstrate all of this.
And I'm gonna do this demonstration by creating
completely new application called Psychologist.
Okay, so, let's go over here.
So I'm going to Xcode.
And here's happiness and calculator.
But I'm gonna create a new project here.
I'm gonna call it psychologist, Psychologist.
Okay this gonna put it in the same place that
my calculator and happiness apps were.
Here it is.
I'm gonna move these things out of the way,
like we always do.
The images, the assets, the launch screen so that I
just have my main storyboard here and this view controller.
And I'm actually gonna rename this view controller.
I don't like the name GenericViewController.
I even had you change it
in the latest homework assignment, because I
just don't think that's a very descriptive name.
So, I'm gonna change the name of
my view controller here to be PsychologistViewController.
So I have to do that in three different places again,
so here I'm gonna say Psychologist.
Here I'm gonna change the name of the file,
to be Psychologist.
That's surprisingly hard to type by the way.
And then in the story board,
of course, I need to go to the identity inspector here and
change it to be a PsychologistViewController.
So let's add those three steps.
So now I have this PsychologistViewController.
What's this Psychologist gonna do?
Well, he can ask you a question like Psychologists
want to do.
And you're gonna give an answer.
And then he's gonna make a diagnosis.
Okay. Based on your answer as to
how happy you are or not.
And then it's gonna use the HappinessViewController,
to show how happy you are, show the diagnosis basically.
Okay, so we are gonna use both the
PsychologistViewController, and
the HappinessViewController from our last app.
But let's start with this psychologist view
controller here, let's build its UI.
He's going to ask a question, so
I'm going to bring out a label for the question.
He's going to ask the question,
what do you see in your dreams?
That sounds like
a very psychologisty kind of question.
And let's make it bigger font.
Maybe like, 36 point or something like that.
We can make it larger here.
Let's center it, make this text centered.
Let's try to put it in a nice place, okay?
Let's use our blue lines to put it somewhere here.
Let's put it like that, so it's nice.
And put it in a good place.
Let's try.
I'm going to show you a little bit of
Auto Layout every lecture.
Just show you the things you can do.
So let's try and see if we can.
We put this all on blue lines up here.
So let's see if we can request, or have it
reset to Suggested Constraints and see if it'll work, okay?
So here I'm, this is for the Selected View.
To un-select this view.
I'm gonna go reset to Suggested Constraints.
Now, let's see what happened.
Now, this doesn't look good.
I don't like this,
cuz I really don't want this thing attached to the bottom.
But the real place, a good place to look for
the constraints is over here again in Size Inspector.
If you look down at the bottom,
you can see all the constraints that that reset to
Suggested Constraints did.
And I'd like this one, and I like that one.
And I like that one.
But I don't like that one.
So I can just click on it and
hit delete, and get rid of that.
Now as soon as I did that,
of course I got the yellow cuz it's misplaced.
So I'm gonna go back and
do what we did all the way, way back in lecture one,
which I'm gonna update this frame, fix the misplacement.
No issues.
Boom. I've got this where I want it.
Okay, so that's another way to use auto layout there.
Alright, so let's get the answers out.
Here's our question.
Let's grab our answers out here.
So let's, maybe I see a dancing tree, okay?
If I see a dancing tree in my grid,
let's make this font bigger again on this one too.
If I see a dancing tree in my dreams I'm probably gonna be
pretty happy I think.
So let's try and put this one where it should be.
So I'm gonna try and
put this one right in the center of my view.
So again, let's try and reset the suggested constraints and
see if that works.
Okay well that looks bad too.
So let's go look over and see what it did.
Alright, well, it aligns center to the super view.
That looks good.
But it aligned the X up with this thing up here and
I don't really want that, so I'm gonna delete that.
The bottom space, I definitely don't want that.
And it fixed the width.
I definitely don't want the width fixed.
I want the width to match whatever the size of
this thing is.
So, kinda got most things here.
But I really don't have a vertical position or
horizontal position of this thing set.
So I'm gonna use another one down here.
This is the alignment one.
And I'm gonna go down here and say, I want the alignment,
the horizontal and vertical centers to be lined up.
So I really already got the vertical center right there.
So I just do horizontal center, so
I'll add that constraint.
So now I've got these two things lined up,
that looks like what I want.
Again, it's a little off this placement probably size is
not quite right, we'll put that right.
And boom, now we've got this tree in the middle.
So let's add some more answers. I'm just going
to copy and paste because I like this font combination.
Let's say you dream of a dirty Golden, no not dirty,
we'll just say, a Golden Bear.
[NOISE] Okay so let's say the Golden Bear somehow shows up
in your dreams.
Doesn't sound very good.
So there's that.
And this one, let's see if we
can do suggested constraints with this one.
Okay, we do that. Now this one looks good.
It's got the bottom space and the center.
Looks good, okay?
So we're rocking with that one.
No need to do anything.
Let's do another one.
Buckeye, I'm not even sure what that is, but
we'll put that in there.
We'll reset suggested constraints for this one too.
Make sure that looks good, yes it does, okay,
this is just the size inspector right here, alright.
Alright, so that's good.
So let's run our app and see how it looks.
Okay, here we go.
Oh, that's doesn't look good.
What do you see is getting cut off?
Let's see, if we rotate.
So it's good in landscape.
It doesn't look very good in portrait.
So why is that happening right there?
Some of you found this out in your homework.
It's because right now,
we have this thing set to be of a fixed size.
The font size are here, see auto shrink, fixed font size.
And that doesn't need to be fixed,
I'm happy if that's any size.
I really don't want it to
be any smaller than like 12 point.
That's getting pretty small in the UI so,
I'm gonna set the minimum size to 12.
And now when we run,
it'll make the font smaller to fit the size.
But if we go to a larger, it will make the font bigger.
Okay. Question back there.
>> Is there any way to make it wrap around to the next line?
>> So the question is,
is there any way to make this text wrap to the next line?
And there is.There's a couple of ways to do it.
There's UI text view,
which is a very powerful text wrapping one.
But even Label, you can go here to the Label and
when you inspect it, you can say,
how you want the line breaks to happen.
You see here it says truncate tail.
And you can also control how many lines long you're gonna
allow the label to be.
Okay, so now we have this good UI, and we want to
make it so that it works with the Happiness View Controller.
So we need our Happiness View Controller.
So how are we going to get our Happiness View Controller?
And the answer is,
we're just going to copy and paste it from our other app.
So let's go open our other app.
Okay, where is it?
It's here, Developer Happiness.
I'm just gonna open Happiness in X code.
Here it is.
And I'm just gonna first of all copy the code over.
So I have my Face view and my Happiness view controller.
I'm just gonna drag them from one into the other.
Okay, just drag them from one project into the other.
When you do, it'll allow you to copy them if you want, or
you could have a reference.
If you're going to have a reference, make sure that that
place you're referencing to stays around,
that you're not deleting it and things like that.
Or you could have a copy.
I'm going to add a copy, the items right here.
Okay, so, copy those two things in.
And then what about my storyboard here?
I need to kind of get this Happiness view
controller over here.
Okay. Over, into this guy.
Okay, well I can copy and paste that too.
Just select this thing, copy.
Go over to here and paste.
So, now I have somewhere my two view controllers.
Now one thing I notice when you do copy and
paste, it doesn't draw the face.
It seems like it needs kind of a little bit of a kick,
a little boost before I do that.
So like if you go to FaceView and
just edit this file and hit save.
It seems like that gives it the kick in the head,
literally, that it needs to draw the head, okay?
So, now we have it.
So, we got our two view controllers here and
we want to put them in a split view.
So that this is the master, and this is the detail.
So let's do that.
Super simple, we're gonna go down here.
Go grab a split view controller, okay?
The split view controller's right here.
See, here's tab bar controller.
Here's navigation controller, somewhere.
Page view controller, even.
We're not gonna talk about that, but
that's another way to combine MVCs.
But let's drag this split view controller out.
Now see how it
comes with other stuff that you don't want?
So when you drop it in there, literally just
select the stuff you don't want and delete it.
Okay. Don't want any of that stuff.
Trying to be helpful.
And so here's my split view controller, okay and
here's my mastering detail.
I'm just gonna control drag.
To set my master.
So here's the master.
And I'm gonna control drag, to set the detail.
Okay. That's it.
So let's run.
Let's actually run on an iPad.
See what this looks like.
[BLANK AUDIO] Alright, so here's an iPad.
Oh, I thought I was gonna get a split view, with this thing.
How come I don't get a split view?
>> [INAUDIBLE] >> What?
>> [INAUDIBLE] >> Yes, exactly.
Very good job.
You should get extra credit or something up there.
Yeah, the problem is this UI comes in through this arrow,
so it comes to here.
So it's bypassing the split view.
It's not even going.
So it's just a common mistake you'll do,
you'll forget to move this.
And you can just pick this arrow up and
move it over here.
Now when we run, it's going to come in, via the split view.
And it is a split view.
If I slide out from the left,
there's my master and here's my detail.
Okay. And if I rotate.
Okay. I get the mastering detail on
the screen at the same time.
Sound good? Now clicking this doesn't seem
to do anything, okay.
So we're gonna have to fix that.
And let's go look at it on an iPhone see what it
looks like there?
I didn't hit the button sorry Alright, here's my iPhone.
How do I?
I can't see the face.
Okay? Let's try landscape.
That doesn't work either.
So there's no way to get at the face, right now.
Absolutely no way to get the face.
And why is that?
Well that's because again on phone which is
a compact size trait device.
Split view doesn't put things side by side,
it just doesn't do that, okay.
Now if we do iPhone6 Plus.
Try that one.
It's kind of a hybrid.
First of all it's such high resolution that even the small
versions, the smallest I can get it.
But see, in portrait,
I have the same problem as another iPhone.
There's just no way for me to get to the face.
Cuz it's no way to,
if I try sliding out from the side, nothing happens.
Okay? Because in portrait mode,
the iPhone 6 Plus works like an iPhone.
But in landscape, on iPhone 6 Plus,
it's big enough, that it can actually show them both.
So that's kinda cool.
Alright but it still doesn't work.
So why does this not work?
Well, it doesn't work because we have no segues.
We don't describe how to get from one of
these things to another.
So let's put some segues in.
What we're gonna do,
well, actually before we do the segues,
let's fix this problem with the iPhone not working.
Okay, let's fix the problem where we can't see the iPhone.
In order to fix that, what we talked about in the slides,
by putting this guy in a navigation controller.
So let's go do that.
We're gonna do that with embed.
In Navigation Controller.
It puts it in a navigation controller, okay.
Now when we run on the iPhone, we'll just run it in normal
iPhone, you'll see that we get the face.
Okay? Awesome.
And we can go back to the master and
there's no way to get back to the detail.
So now we definitely need those segues.
We need these buttons to cause a segue to happen to
the detail.'
Okay. So
that's what we're gonna do next.
And actually, let's take a second here and
show what this looks like on the iPad.
We added the navigation controller here.
Let's see what effect it had on the iPad.
And the answer is, that the master now has a title.
Has a title there.
And this kind of would be nice,
even to put a title in here.
So we can go over here, and actually double click on here,
and put in psychologist.
Put a title in there.
Notice, look what happened to our question.
It kind of got obscured.
Do you see that?
By this title.
And actually we have a warning up here.
Do you see that warning?
That warning is about that.
Let's click on it.
It says, the frame for
what you see in your dreams will be different at run time.
That's because it's going to automatically move it down
underneath this.
And we can make that happen in our storyboard by going over
here, clicking here, doing what we always do when we
have a problem with our auto layout,
fix our misplacement and it will move it back down.
Alright so this is looking good.
So let's get this segue business happening.
So I told you the segues are done just with control drag.
When we click one of these things I wanna segue to
a face that shows the diagnosis based on
what you saw in your dreams.
So we do this just with Ctrl+drag.
So let's Ctrl+drag from Golden Bear.
Down here.
See how it's grabbing on to this MVC down here?
So we'll let go and
it says what kind of segue do you want?
And we're going to do show detail because we want it to
show it in the detail side of the split view, and
in the navigation control it will just push it.
But the show detail will do the split view thing.
So, there we go and
look what happened there we got this little segue.
If we inspect it, over here,
you can see there is its identifier.
You can even change what kind of
segue it is in the future if you wanted.
But this identifier is the Golden Bear one.
I'm going to call this the sad identifier, okay.
So whenever this goes through,
this identifier for this segue, is called sad.
And we'll do the same thing here for
Dancing Tree, okay, show detail again.
And dancing trees segue, which is right here.
We're gonna call this one, happy.
That's the happy one.
Now, I told you these should be verbs so
maybe this should be,
show happy diagnosis, show sad diagnosis.
But for demo it's less typing later,
I'm just putting happy in that.
How about buckeye.
Okay, we'll say show detail.
And for the buckeye one.
Where is that one?
That's this one I guess.
We'll say meh.
Okay, not happy or sad.
Okay, and you can move these things around.
Right, if you're having trouble selecting them or
whatever, you can move them around to get at them better.
So this is what our storyboard looks like now.
Let's make some more space so you can see it, right here.
And we've got our detail.
Let me whip this up here.
And we got our master and we've got the segues now.
So let's go ahead and run, and see if this works.
Let's go.
On i-Pad, okay, huh, does not appear to work on the i-Pad,
huh, that's interesting.
Alright, let's try it on the i-Phone.
All right, so there's iPhone.
So we're at the face, let's go back to the master.
Here's the master,
notice we have this nice title up here now, Psychologist.
Let's do this.
Oh, it's doing something, but,
it's not actually showing the diagnosis.
But at least it's segueing to the other one.
So the iPad was working too, it's just there was nothing to
see, because there was already a detail there and
it replaced that detail with a new one.
But we didn't prepare that thing, so it doesn't know how
much to smile, it doesn't know how to show the diagnosis,
cuz we have to prepare it.
Okay, so preparing is the next step.
We do the preparation for
these segues in this ViewController.
This is the ViewController that's instigating the segue,
so here's where we have to put our preparation.
This is the PsychologistViewController.
Okay, so we're gonna go over here to
our PsychologistViewController code, delete that stuff.
Okay, here's PsychologistViewController.
And all we have to do here is implement that one prepare
method, okay.
So it's called prepareForSegue.
'Kay, I'll let it type it out for me by hitting tab.
And you can see there's the two arguments, the segue and
the sender.
Now I'm gonna just say here, if the segue's
destination view controller, sorry, if I can let HVC,
HappinessViewController, equal the DestinationViewController
as a HappinessViewController, then I'm gonna do
something based on what the identifier is.
Now, if this segue, if we have a prepareForSegue and we're
segueing to something that's not a HappinessViewController,
then this if let is not gonna happen.
So none of what I'm gonna type right here is gonna happen,
and that's perfectly fine.
You can kinda do the if let on what kind of
thing you're segueing to, or
on the identifier, one on the outside,
one on the inside, kind of depends on what's going on.
But in this case, I'm going to do the if let for
my destinationViewController on the outside, and then I'm
going to do the if let on the identifier on the inside.
Okay? So if I had a segue to
a happiness controller that had no identifier set,
then we would do nothing.
But if it's set, we're going to go in here,
we'll switch on it.
So let's switch on identifier.
If it is the sad identifier, okay,
the sad segue, then let's set our hvc's happiness to 0.
Okay, so here's where I'm preparing, this newly created
HappinessViewController to be displayed on screen.
Okay, and if it's the happy segue,
then we'll set the happiness to 100.
And then, actually for
anything else, I'm just gonna set the happiness to 50.
Okay, something in the middle.
Okay, so that's it, that's all I have to do here,
that's all my ViewController needs to be prepared.
You know, if I had other things in here, I could
set other properties, but this is all this one needs.
So it's prepared.
So let's go ahead and run this.
This should all work, right?
It should be no problems.
Okay. Here's our psychologist.
Let's try dancing tree.
Oh, crashed our program.
All right, kind of told you I was going to do this.
Why did our program crash?
Well it says unexpected,
I'm looking in the console down here.
You should always look in the console when it crashes.
Okay? It's the first place
you want to look.
This says unexpected found nil while unwrapping an optional.
Okay, so I accessed some optional that was nil.
So that's bad.
Where did I do that?
Right here in updateUI, in HappinessViewController,
HappinessViewController updateUI.
Well, let's see, what in this line might be nil?
Well, of course, it's the only thing that could be nil,
which is the faceView is nil.
What is the faceView?
It's this outlet right here.
Okay, we can also, by the way, go over here and
find out how we got here.
So we got here because someone was setting our
model into the property observer,
we wanted to update UI, and we got there from preparation.
So here we are preparing,
we're trying to prepare this new MVC, and
it sets the model to be something,
that updates the UI, and we get here and we crash.
And why is faceView nil right there?
Because as I said in red,
when you're preparing the outlets have not been set.
So this faceView outlet, down here, has not been set.
So, you know, it's an implicit unwrapped optional, but
it's still an optional, and it has not been set yet.
Okay, so how are we going to get around this?
Well, luckily in our case, whenever we set, if we set our
model and we try to update the UI and the faceView's not
even connected yet, well, we can just ignore it then,
because obviously the faceView is up to date because it's
not even hooked up.
So we can just use optional chaining here and
just put a question mark there.
Right, and what that says, if this thing is nil,
than just ignore the rest of this statement.
So, one thing you'll probably end up doing a lot of times
is, in the things that could be called from a prepare,
you might be putting this optional chaining in.
Or checking, if base view does not equal nil,
then do something.
So that should fix that.
Let's go ahead and run this.
Here it is.
Let's go back.
Dancing tree, very happy.
Golden bear, very unhappy.
Working fine, let's go take a look, and
let's go look in landscape here.
Golden Bear, working fine.
Notice that this MVC underlaps this title bar up here.
You can actually control that in storyboard if you inspect
the MVC, you can click on there,
say do not go under thing above me.
Also notice that in landscape,
you get a little smaller title bar up here,
which is kind of nice.
But back in here, you get the bigger one,
because you're getting the carrier and the time up here.
Okay, let's go look at it on the iPad.
Okay, here's this, I can slide this thing out from the right,
Golden Bear, Dancing Tree, Buckeye, working great.
We can go over here.
Golden Bear, Dancing Tree, Buckeye.
So pretty straightforward, the stuff is all pretty easy to
envisualize in your storyboard,
when you're looking at the storyboard it's pretty clear,
once you understand how these connections happen, to see
what's going on over here.
Okay, so one other thing I want to do here is make,
let me go back to my simulator.
Look at this guy over here.
This guy doesn't get a title.
That's kind of a bummer, that he doesn't get a title right
there and he does on the iPhone.
Right, if you remember on the iPhone, he had a title,
it was blank, but he had a title.
So I wanna give this guy a title on the iPad as well.
So I'm gonna do that by just selecting it here and
saying Embed In > Navigation Controller.
So I put this guy in
a Navigation Controller too, down here.
So then, I can have a title.
Now, I could click here to set the title, right here I
could say diagnosis or something like that,
but actually I am going to have the title be set in code.
What I'm going to do is, every time someone says for my model
in my HappinessViewController, when I update the UI,
I'm going to say my title equals my happiness.
So I'm just gonna put that integer,
which is my happiness, as my title.
So I'm gonna put that in here let's see if that works.
So we run, I've got a title.
Doesn't look I've got there, but
no one has set my happiness yet, so that makes sense.
Oh, but it looks like I've
broken something by doing that.
This doesn't work.
Why doesn't this work?
Well, the reason this doesn't work is because these segues
are seguing now to a Navigation Controller.
They're not seguing directly to a HappinessViewController.
So this prepare that we have right here,
this very first line is going to not work.
Because the destinationViewController is
no longer a HappinessController,
it's a NavigationController.
Everyone understand that?
So how can we deal with that?
Well, that's actually quite easy to deal with.
I'm gonna create a variable here called destination, which
I'm gonna set equal to the destinationViewController as
a UIViewController,
cuz I know it's a UIViewController of some sort.
And then I'm gonna say, if I can let navCon equal
the destination as a UI Navigation Controller,
okay, then I'm going to set the destination to be the nav
cons, and what I want is the visible ViewController,
the one on top of the stack.
So I'm going to say, .visibleViewController.
So visibleViewController is just a property in
UINavigationController that returns to the one
that's on top of the stack,
which is going to be HappinessViewController,
because it's the only one on the stack.
Okay. And
then here, instead of saying destinationViewController
here, I'll just say destination.
So now, if we come in here and
this is the HappinessViewController,
in other words, I don't have the navigation controller,
then this is not even going to happen.
And so it's fine.
This will work.
Otherwise, if it's a navigation controller,
I'm going to pull the HappinessViewController out of
it, and then this'll work again.
So it would have worked in either case.
So this is nice, in your prepares,
to make it so that if you ever think that the thing you're
segueing to might be wrapped in a navigation controller,
this will make it so it'll work either way.
So later, if you decide to unwrap it or
whatever, this'll work.
So let's try this.
All right, so
we've got this Golden Bear, there's the title and
it's working, 100, Buckeye, that's working too.
Make sense there?
All right, the last thing I want to show here is
briefly how to do a segue in code.
Because this segue we did with control dragging in
the storyboard entirely.
So how would we do a segue in code?
So let's do a different segue here,
I'm gonna add another thing to this.
Let's go down here and add a new button right here.
Put it in here, I'm going to call this Nothing.
So what do I see in my dreams?
I don't see anything.
Okay and I am going to put that here.
I'm going to try Reset to Suggested Constraints.
I'm going to check to see what it did.
That looks perfectly fine to me.
I'm rocking!
But instead of control dragging from here to make
this segue, I'm just going to create a normal target
action method.
So this is I'm just gonna make this be a completely normal
button that's going to do target action from here.
Okay, so let's make some space over here in our
I'm gonna Ctrl+drag over to here.
Okay, it's gonna be an action.
I'm gonna call it the nothing action.
I'm gonna have the center be a UI button, and Connect.
So now every time I click on Nothing,
it's going to do this target action right here.
And what I wanna do inside here is cause a segue
to happen.
So base this segue in code, so how am I gonna do that?
Well, I still have to create the segue in the storyboard.
Okay, so I'm still going to go back here and
create the segue, but
the question is where do I create the segue from?
Where do I drag from?
Since I don't want this to directly cause it,
and the answer is, I drag from this little thing up here.
Do you see this little yellow guy?
This yellow thing represents the ViewController.
So, when you're setting up a segue that's gonna be
fired off in code,
you do the control drag from this little yellow thing.
So, let's go down here.
I'm gonna take this guy and I'm gonna control drag over to
here, to this navigation controller.
Sorry for the screen resolution there.
It's still gonna be a show detail segue.
I'm going to now zoom out.
Okay, let's find this thing.
It's not that one, it's not that one, it's this one.
And so notice that when I select this one,
it's showing the whole view controller sending this, and
so we will call this the nothing segue.
Okay, so now we have this segue named nothing,
it's not hooked up to any button or anything like that.
Okay, but if I go over to my PsychologistViewController,
now in nothing I can say, let's make this nice and wide,
performSegueWithIdentifier the nothing segue.
And the sender, we could make it be the button or
we could make this actually be self, so
that the view control itself could be the sender.
Or we could make it be nil.
But this sender, whatever we put here is just going to get
passed along when we get a chance to prepare.
Because this segue, even though we are executing it
from code, is still going to get a chance to prepare.
So if we went down here and said case nothing,
maybe the happiness there is not very happy,
okay, then you can still prepare down here.
So even though we are doing it in code,
it's still going to prepare.
All right, so let's go take a look at that.
Back to our iPad here.
So there's happy, sad, and here's nothing.
Make sense?
So you can do things from code.
Now why would you ever wanna do it in code?
Well, maybe you want to have a button clicked, and then,
depending on the state of something,
it'll do one segue versus doing another segue.
So you can have a little if then there that performs one
of two different segues.
That's a classic reason you might want to
do segues in code
versus just control dragging directly from the button.
All right?
I believe that's all I wanted to cover today on that, yes.
So now we'll go talk about popovers, so
let's go back to our slides here.
All right, popovers.
So I don't talk about popovers with the other three, because
it's a little bit different, a popover's a little different.
So here is a UI that has a popover in it.
This is the calendar app.
And you can see the popover is that whole area there where
I'm searching in my calendar trying to find something.
So that whole popover, that little lighter colored area in
the upper righthand corner, that is all one MVC.
It's the search for appointment MVC, okay?
So and it completely fills that popover space.
Now, notice that the popover also has kind of
a little arrow.
You see that tiny little arrow?
It's just like a little white triangle.
That's pointing to whatever caused this to come up.
So in this case,
that little thing that looks like a magnifying glass,
that's what the user must have pressed on in order to
have this pop-over for searching come up.
Now notice the rest of the screen here is gray,
except for the keyboard, is gray.
See it's kind of grayed out?
And it's also if you tried to click in there,
it wouldn't work.
Like if you tried to click on the Week button at the top,
or the Month button or the Year button it wouldn't work.
But what it would do is dismiss the popover, okay?
So that grey area, so you can see that it's not as
bad as take over the screen, but it's still the case that I
can only do what the popover is asking me to do.
I can't do anything else until I dismiss the popover but
it's just really, really easy to see what the rest of
what was going on before you brought the popover up,
and it's usually easy to get rid of the popover.
Now, the interesting thing about popover, and
the reason I talk about it differently,
is that it's not a UIViewController.
Okay. Popover is itself,
not a UIViewController.
It's brought on
screen using what's called a presentation controller.
And I'm not really going to talk about presentation
controller, just a little bit about the popover presentation
controller, but it's the underlying mechanism that all
of this stuff is based on, so popover doesn't really need to
have a view controller whose view is this MVC.
It can do it
purely with the presentation controller mechanism.
So let's talk about the popover then,
and how we make it work, because the interesting of
Power Popover that even though it's not its own MVC,
it still segues and all that stuff exactly the same.
You still Ctrl+drag to some view controller.
You still get to do prepare for segue.
It all looks exactly the same because it's still doing
segues even though it's not its own view controller.
It's still using segues to cause it to appear.
So, things to note when you're preparing for a segue here.
One is that inside your preparer you
can get ahold of what's called the presentation controller.
And the presentation controller for
a popover will tell you things like what's the button that
brought this popover up.
And you can even configure the presentation like I don't want
this popover to pop up to the left of anything.
I always want it on the right side of something.
So you can even control that.
And very interestingly using the presentation controller's
delegate, this is the first time we
have talked about a delegate in iOS in this class,
although we'll gonna talk about it in spades next week.
Using the presentation controller's delegate,
you can affect how the popover adapts to being on an iPhone.
So a popover on an iPad pops up like you saw in
the previous screen there.
A little window that pops up.
Well on the iPhone it adapts and
instead does modal, full-screen, okay?
So it doesn't pop up as a little thing on an iPhone.
And why is that?
Well, the iPhone's smaller and
so if the thing you're popping up is really big,
there might be no way to cram it in there and make it fit.
But if you present full screen modal,
it's definitely going to fit.
Okay, so it automatically does this.
iOS automatically does this adaptation for you,
just like it automatically adapts to split view and
navigation controller if you build your storyboard right
on iPhone, but using the delegate or the presentation
control, you can actually affect that adaptation.
Okay. So, here is a brief slide.
We'll have a brief slide that talks about that in a second.
But, first I want to show you how in prepare for segue you
get a hold of that popover presentation controller and
you can do something like set this delegate.
So this prepare for segue all of the green is basically
the same as you would have in any other prepare for segue.
But the yellow line there is where I am,
from the view controller that I'm segue-ing to,
I'm asking for it's popover presentation controller.
So this is an object, the presentation controller,
that will only come back non-nil, here,
if I'm being segued via popover.
If I'm being segued some other way,
like just pushing in a navigation controller, or
something like that, then this'll come back nil, and
I'm just gonna ignore it, cuz I do if let right there.
But if it is popover, then I make it this popover
presentation controller and if you go look in
the documentation for popover presentation controller,
you'll see it has some things you can configure about
the presentation like the permitted arrow directions,
that little white triangle.
Where is that allowed to point?
In what direction?
And you can also set yourself,
the controller, you know you add the controller as
the delegate of the presentation controller.
Okay, so
when you set yourself as the delegate, what can you do?
What is it going to offer to let you do?
Well, there's a number of things, but
I'm gonna talk about this adaptation behavior.
So here's two methods that are in the protocol for
the delegate there.
One is called adapter presentation,
presentation style for presentation controller.
Okay, so when the popover is trying to present, it's going
to ask you, how do you want me to adapt if I'm on an iPhone?
Now by default, this is going to say full screen modal, but
you can say you want modal presentation style none
which means don't adapt.
So presented on the iPhone exactly like you do
on the iPad.
Okay, so for
a small popover, this makes a lot of sense, okay.
So this is how you can basically turn off
that adaptation behavior.
You can even go way more powerful than that,
the other one here presentation controller view,
view controller for adapted presentation style,
you can return a whole other MVC on the iPhone.
That displays your MVC in a totally different way
maybe it's wrapped in a navigation controller or
it can be completely different.
So you can really customize it but I just wanted to
show the this first one because it's common to say oh
I just have this small little pop over thing.
I want it to look like a pop over on an iPhone and
this is how you do that.
The last thing about popover that's important is the size.
So you'd really like the popover to come up and
be exactly the right size to fit the MVC
because your MVC might be different sizes, okay?
Even as a given MVC might be different sizes and so
you really wanna be able to control the size.
And in a really object oriented way,
the way the system does that, is it asks the MVC that is in
the popover what is your preferred size?
What would you like to be if I could grant your wish,
what would you like to be, okay?
So it's cuz only that MVC really knows what
its preferred or ideal size might be.
Now that's only a recommendation because
the popover has some constraints as well, right?
Because it can only appear in certain places on screen, and
the screen is only so big, and those arrows might have to go
a certain direction, they might be restricted, so
the popover has got its own things to deal with.
But it's going to ask the MVC it's putting inside of
itself what would you like to be?
And so this is just a property in your eye view controller.
You can, for example, override this.
Okay. Override the property and
return your preferred size.
Or you can set.
It's a settable property so
you can set your preferred size.
If your preferred size is always an exact size just set
your preferred size to that.
Or, if you have to calculate your preferred size based on
what your content is, which you're going to
see in the demo that I'm going to show about popovers
in a moment here, than you can override it,
which is what I did in that demo.
'Kay, so, we're gonna have
a demo here which is adding a popover to psychologists.
Popovers I
made them extra credit on your homework assignment.
So you don't have to do them but I recommend doing it cuz
it's a good experience to make a popover.
Okay, it is something.
If I had enough kind of room in your assignment to
fit popovers, I wouldn't have made it extra credit, but
I just feel I have only given you one week's worth of work,
I don't want to over burden you,
but this is an extra credit you really want to try to do,
I think, if you can.
Because in your final project, you're almost certainly going
to have some reason, hopefully to put a popover in there.
Okay now before I do the demo let me talk about
what's coming up because I never go back to the slides.
Friday we are gonna have that Friday section again for
IT & T people sorry it's not gonna be on video.
It's not in a room that we can do the video in really.
So that should be a good one.
And that's also an extra credit item in
your homework is to analyze your performance of your
calculator that you're doing, your graphing calculator.
And find out where it's slow and
then maybe you can fix it if you want,
that's another extra credit to try and go fix it.
Next Monday I'm
going to dive into the View Controller Lifecycle.
I hate to have had put the View Controller Lifecycle onff
for so long.
But in some ways it's kind of nice because it forces you to
use other parts of your View Controller,
like the property observers in your outlets, and
in your model setting, and things ike that.
But you're going to find out on Monday, you're
probably going to be mad at me on Monday when I show you
all these nice methods in the View Controller Lifecycle and
you're, like oh if you'd just told me that last week it
could have made something so much easier.
But the homeworks are designed to not need any of the view
controller life cycle methods, you shouldn't need them for
anything, even for the extra credits, you shouldn't.
And then again, I have autolayout question mark,
kind of a running joke,
we'll see, hopefully we'll get to autolayout eventually in
this quarter, but like I say, see I'm kind of sprinkling it
in in every demo, a little bit of autolayout, so
hopefully you're learning a little bit along the way.
And then, after Monday, we'll start diving into
multithreading, because you're talking about a device,
a phone, that needs to be highly responsive to the user.
Okay? It needs to
always be responding to touches.
It cannot, you press a touch and then it freezes for
two seconds or even a second, while it goes off and
does something.
It needs to immediately animating a response to
what you're doing.
So the only way to make that work if you're doing things
like accessing the network, which is really slow,
compared to the things you're doing on-screen,
you need to be able to do those things offline of
the main thread of execution, so we'll talk about that.
Then we'll start talking about scrolling.
Because you've got this small screen.
It's nice because it fits in your pocket but
if you want to show something big,
you need to be able to scroll around in it.
If you want to see a nice image and
you want to zoom in and see a really detailed part of it,
you have to be able to zoom in and scroll around.
And then we're going to talk about the next big thing and
the topic of your next homework after the calculator.
Which is, I know you love the calculator, but
this is your last assignment for the calculator.
We're going to move on to a whole thing called table view.
Which is really highly delicate based user interface
mechanism in iOS that really helps you understand
how iOS works when it comes to sophisticated user interface.
Okay? So that's what we're going to
be doing next week.
All right?
Thank you.
Okay. So,
let's continue with our psychologist demo, here.
We're going to add a popover.
And the place I'm gonna add a popover is down here, okay?
In this HappinessViewController, here,
I'm gonna put a little button, here.
And this popover is going to show the history of
all the diagnoses made by the psychologist.
So the psychologist is going to be diagnosing things as we
click on what we see in our dreams, and
we're going to want a little button here that brings up
a popover right here, and
this popover is going to show the history of the diagnoses.
Now since this is a demo, I wanna keep the code simple.
It's gonna show the history of the diagnosis just as
an array of ints, because we know that our happiness is
represented in int.
So it's gonna be shown in an array of ints.
It might be nicer to show it in a different way, but
we're gonna show it as an array of ints.
So let's build this popover segue first and
then we'll have to go on to build a brand new MVC,
actually, to show the information.
It's just gonna be a simple MVC that shows text only, so
we'll have to do that.
And then we're obviously gonna prepare this segue.
But first let's build the ui portion of this and to do that
I need to add a little bar but here is so I'm going to
bring up my object palette here and zoom in on this guy.
And when you put a button here you don't use this UI button.
Okay so UI buttons, even if you drag the UI Button here it
will look like it is going to work but
actually don't do that, it will mess you up.
Instead you want to go down here quite a ways
towards the very bottom and there is this Bar Button Item.
Bar Button Items is a little lighter weight button that
goes in bars like this, navigation bars and tool bars.
So I should put that one right there.
We'll call this one history since it's the diagnostic
history of what's going on with this patient right here.
And of course if we're gonna have a popover,
the popover shows a MVC.
So we need to create a new MVC.
So let's go back to the top here and get ourselves
brand new view controllers, this is just the regular old
view controller like we've dragged out before, so
I'm just gonna drag that right in here, and make some room.
So here we have this, zoom out a little so
you can see it a little better, and
what we want is for this little button to segue to this
MVC, and show it in a little popover right here.
Okay? So that's all we
wanna do there.
So let's just Ctrl+Drag, just like we
created in the other segue, we're gonna Ctrl+Drag from
the history button over to this MVC, and when we let go,
it's gonna say well, what kind of segue do you want?
And we want the propover presentation segue right here.
So I'm gonna click that.
This is a popover.
If I click here, on the segue, and go to the attributes
inspector here, you can see that it is a popover segue.
I can control where the little arrow, if you remember
the slide about the popover, there was a little kind of
triangle that was pointing at the thing that brought it up.
Like this History button, or
in that slide it was a little search button.
So I can control which direction that arrow pointed.
And I can even see here the anchor.
See it highlighting there.
That is going to bring up this popover.
So that's great.
And of course I need an identifier,
just like any other segue, I need an identifier.
So, this shows the diagnostic history, so
I'm gonna call this Show Diagnostic History.
Oh, my caps lock.
There she is, there.
History, there we go.
Show Diagnostic History.
So now we've got this set up to this segue and
show this MVC.
Now, this MVC is just a blank MVC right now,
but let's go ahead and run and see what this looks like.
So this is going to show a blank MVC at this point.
So here's our iPad right here and we'll.
Go to Landscape Mode.
And so if I click on this,
you see I get this nice blank MVC appearing right here.
So our next step in this is we need to create this MVC.
All right, we're going to.
Create the MVC that is going to go in here.
It's going to be a very, very simple little MVC.
It's just going to have a text view in it here to show text.
And that's all it's gonna do is show text.
It doesn't do anything else.
So, let's start by creating a new
UI view controller subclass.
So again I'm gonna go to iOS source cocoa touch class here
because I'm gonna create a cocoa touch class, and
it is gonna be a UI view controller.
I'm gonna call it text UI view controller because that's what
it does, it shows some text.
That's all this view controller knows how to do.
I'm gonna put it in the same place all the rest of
my SWF files are.
Okay, here it is.
Here's the code for it.
We're gonna delete all of this stuff in here.
Right, so we've got a nice subclass of UIViewController.
We'll have to put our implementation in here.
Meanwhile, let's go back to our storyboard and
make sure that we set this thing's class in
the identity inspector up here.
To be the text view controller, so
that we know this is a text view controller.
Now, let's talk about this thing's UI.
It has a very simple UI.
I'm actually gonna drag out a text displaying object here.
And I'm not going to use label.
Label is nice for one and two and
maybe three lines of static text.
But I really want something that kind of can show as
much diagnostic history as I want it.
So I want something that shows a lot more text.
A text field is
not really appropriate because that's editable.
One, two, three liner.
So label and text field are very similar.
It's just editable or not.
But there's yet
another one down here, called text view, right here.
And this displays multiple lines of editable text.
It lets you set the font, and the text can be selectable.
You can copy and paste from it, things like that.
So it's a much more powerful text styler, but
we'll talk about this later in the quarter.
But for now I'm just going to drag this in right here.
You noticed I used the blue lines.
I'm going to go up here and
reset to suggested constraints.
I'm going to go over here to the size inspector up here.
And verify that my constraints are the way I want, and
they look fine.
Okay, so that's good.
I could also set some attributes maybe, about this
text view, like I probably don't want it to be editable.
I don't want the diagnostic history to be actually,
you know, touched on and edited.
But it's not bad to have it selectable,
someone might wanna select the diagnostic history and
then copy it and
paste it somewhere, or something like that.
Or you could set the font to be larger too,
maybe something 24 point or something like that.
And of course we've got this kind of
pseudo latin placeholder text right here.
But that's not gonna matter cuz that's not
gonna show because we're going to
set the text we want when we prepare for this segue, okay?
So now let's go ahead and wire up this UI.
We've got this text view right here.
Let's Ctrl + Drag to create an outlet to it, okay?
I'm gonna call that outlet text view.
So, we've got a nice outlet here.
And let's add a model to our text view controller.
My model, I'm going to call it text.
It's going to be a string.
We'll start out as an empty string.
Now every time my model gets set,
I want to make sure that I update my text views text.
So text view is this thing that manages text.
And you can see has an enormous number of things you
can do on it it's a very powerful text object, but
it also has just a simple method called text.
Just like UI label does, and we're gonna set that equal to
our text the model's text right.
And just to be safe in case this is being called while
we're preparing.
Okay, we'll do the same thing with optional chaining in
case our outlet here has not been set.
And similarly when our outlet finally does get
set by the system, we're going to have it, property observer,
say text view dot text equals text.
Okay. And here we don't have to do
the question mark because where actually the text view
is being set by the system, so
we know it's set by the time this didSet happens.
Okay, so this is a very,
very simple MVC that we're using right here.
And it should have no
problem displaying our little diagnostic history, there.
So now it's time to prepare this segue.
All right? We want to
prepare this segue so that you click on history,
it shows the diagnostic history here now.
We might, we know that this instigator right here is
inside this happiness view controller.
So we might think that we should go to our happiness
view controller right here and add the prepare in here.
Okay. And we could do that but
remember that happiness view control is
something we dragged in from another app.
And maybe that's another app that's being worked on at
our company or that there's another programer who
owns this particular class.
And he said no, no,
you can't add prepare for segue to this class.
It's a generic happiness showing thing.
It doesn't know anything about diagnostic history.
And they'd probably be right because if we started
adding things about diagnostic history to a happiness view
controller, it would be kind of a diagnostic or
diagnosed happiness view controller not
a happiness view controller anymore.
So where are we going to put our prepare for segue then?
The answer is that we are going to
actually create a subclass of
happiness view controller that we can use that's going to get
all the behavior of happiness view controller.
Plus, we're going to add the ability to do
the diagnostic history.
Okay. So we're going to
create a subclass.
We're just going to go up here.
New file.
Again, I'm just going to create a SWF file this time.
I'm going to call it diagnosed happiness view controller.
Okay, because it's just like a happiness controller, but
it's diagnosed happiness.
Here it is right here.
I'm gonna import UI kit because it's a UI class.
And I'm just gonna say that my class
diagnosed happiness view controller inherits from
happiness view controller, okay?
So I am going to be
a sub class that diagnosed happiness view controller.
Make sense?
Now, over here in my storyboard,
I am going to select this scene right here.
And I'm going to go to the identity inspector, and
I am going to say that this scene is no
longer a happiness view controller.
It is a diagnosed happiness view controller.
So now I'm this guy here.
Now, all my outlets that were set up will
work absolutely just fine.
Okay? Because I'm gonna inherit all
the capability of happiness view controller in my
diagnosed happiness view controller subclass.
In fact, what's really cool is I have a scene right here.
And this scene is a diagnose happiness view controller.
But if I go up here to pick a different class.
If I go back and
pick my happiness view controller, and I see it here.
You can see that it'll show me that that's hooked up.
Okay, cuz it knows that this is inherited,
this outlet is inherited.
And so it's hooked up.
So I can still go back and show my
superclasses for my diagnose happiness view controller to
happiness view controller, and see the outlets.
Okay? So this is an important thing.
Polymorphism of controllers, here.
You often might have a reusable controller.
And you wanna add something to it for
a particular storyboard or
a particular use in the storyboard.
Then you can just create a little subclass of it and
put your prepare.
So what we're gonna do is put our prepare right in here.
So this
DiagnosedHappinessViewControl- ler, first of all it's
going to have to keep track of the diagnosed happinesses.
Okay. So we're gonna add a new var
to this subclass called diagnosed happiness.
Or diagnostic history, let's call it.
Okay it's the diagnostic history of this thing,
and we're just gonna keep it as an array of ints.
So we've got our nice diagnostic history right
there, and now let's go ahead and let's do this.
Let's go here and here and
here to give ourselves some room.
And let's override.
Actually, we don't even have to type the override here
because we start typing prepare for segway end tab.
It's going to automatically put
the override func in there for us, which is nice.
We don't have to be typing this unnecessarily.
So here's our repair for segue.
And so all we're going to be doing in this prepare for
segue is prepare our text to view controller, all right?
Because our text view controller, here,
is what we're seguing to.
So we're preparing this segue right here.
So we wanna prepare this MVC,
which is a text view controller, okay?
So let's prepare that.
And let's, first of all, make sure that this is
the segue we're talking about, here.
So let's go right here, check our identifiers,
get our identifier out of there.
Let's switch on our identifier.
Currently, we only support this one case.
I'm also going to put this case,
this is something you should probably always do,
which is to put the segue identifier here into some
sort of constants struct.
I'm gonna call this my history struct.
I'm going to have, and let me make sure this is private.
Oops. Let's type
this correctly here, private.
All right.
I'm going to have this be static let
segue equal that show diagnostic history.
So this would be a segue identifier.
Maybe we'd even want to call this identifier,
segue identifier.
All right.
All right, so putting this in here it just, you know,
collects all your constant strings together.
And if you ever change something in your storybook.
Some people might even call this struct storyboard, so
that every string that's in your storyboard that has to
match up here in their code, is in one struct.
We'll call this one History right here.
It's kind of debatable which way to go there.
So what do
we want to do when that history identifier happens?
Well, if we can get our segue's destination view
controller as a text view controller,
that's the only thing we need to segue to with this segue.
Then we're just going to set the tvc's text equal to
our diagnostic history,
which I'm going to do by diagnostic history.
So, it's just going to show this array,
this diagnostic history array, as a string.
All right.
And of course we'll need the default.
Break out of here.
Okay? So there we
have this nice diagnostic history.
So let's go ahead and run this and see if this is working.
All right, so again we click here.
And, well, it seems to be working,
cuz it's showing no diagnostic history.
I haven't clicked any of these.
So, since we added this code,
anyway, I haven't gotten any diagnosis, so that's good.
So let's dismiss that.
And here, I'm gonna go there, go there.
Oh, it's not working.
So why is it not working?
Okay, well, we have this nice diagnostic history, but
we never actually set it.
Okay, it's always just empty.
And so how are we gonna set it, though?
We are sub class of happiness view controller.
Well, we can just override our var happiness from
our super class, and do a did set of our own in here.
So that happiness has its own did set.
And we're gonna add our own did set here,
which is we're gonna say the diagnosing history plus equals
the happiness, okay?
You can use plus equals with an array but
you have to remember that the argument has to be an array,
so if you just want to add one thing,
you can just wrap a little array around it here, okay?
So here, it's perfectly fine to override a bar from your
super class.
If you go look at our super class,
happiness It has a var and even does it's own didsets.
So I'm over riding this var, and I do my own didset,
it does not override or replace this didset.
So it's gonna do this didset, and
then it's gonna do this didset.
So, it'll do both of them.
So it's a really nice feature, the property observers,
when you override they don't replace the super class as
one, they add on to it.
So now our diagnostic history is being added.
So hopefully now when we go and
look in our diagnostic history, it will work.
So here we'll go dancing tree.
Look up here.
And look at that!
We've got our diagnostic history.
Let's go over and do golden bear.
That's kind of interesting.
This is not a very good history.
It's only remembering the last thing I redo.
I wonder why it only remembers the last thing I redo.
That's bad.
That's a bug.
So, why has that happened?
Well, I did it this way to show you, and to remind you,
that these segues, all of these segues that
are happening here, they are always creating a new MVC.
So this segue, when we click on golden bear, dancing tree,
and it segues to this, it creates a brand new MVC.
And since this is a brand new diagnosed happiness view
controller, it's going to get a brand new
diagnostic history, which is going to be empty.
So it is constantly going to
be reentering it every time we segue.
We really need to
store this diagnostic history somewhere else.
We can't just have it be in afar here.
And a great place to have permanent storage, of course,
is in its future defaults.
So let's change this diagnostic history.
Instead of being a stored property here,
let's change it to be a computed property.
So I'm gonna have it be an Int.
And it's gonna become computed, so
it's gonna have a get.
And the set.
And in the get and the set here, and
I'm gonna go into user defaults.
Put this diagnostic history into user defaults, and
out of user defaults.
Since I'm going to be using user defaults,
I'm just gonna create a little private let called defaults.
Which is just gonna be the
NSUserDefaults.standardUserDe- faults.
You remember this is like a shared version of any of
those UserDefaults that we get.
The whole app is gonna be sharing this, and
using it to read and write from NSUserDefaults.
Okay. This is nice,
it's convenient to have this.
Makes the code a little more readable to
have this be repeated everywhere,
versus just this little short thing right here.
All right. So how am I going to get the
defaults and set the defaults, well let's do set first.
Once we set maybe it will be easier to imagine our get.
So I am just going to go to defaults,
I am going to set an object and remember that this is
any object, but it has to be a property list, okay?
But luckily an array of ints,
which is what our diagnostic history is.
Sorry, this isn't an array of ints,
this diagnose is an array of ints,
that is a property so luckily, we can do that.
And here we're in the setting, okay, so
we're just gonna put our new value here.
So that's gonna be an array of ints, the new value.
For key we need a key, so let's go back down to
our constants here and add another one, and
this is going to be our called defaults key, for the history.
And we can really put anything we want in here, any name for
the key, but remember that default is a database that is
shared in our entire application, so we might want
to kind of name space it a little bit by saying
diagnosedHappinessViewControl- ler.History or
something like that.
So this is just a naming convention to throw the name
of the ViewContoller or the name of the class in general.
That is writing to the default in front.
You don't have to do this.
This is purely something you just want to be consistent
with in your whole application and
how you divide up this name space for the defaults,
because this is a global name space inside your application.
So this will be our History and DefaultsKey.
All right, so that's the new write our any time we set this
diagnostic history it's gonna write it out to user defaults.
Then similarly we can get it
out by just returning defaults.objectForKey.
Same thing.
This History.DefaultsKey.
But one thing I wanna make sure of is that it's
always an array of int.
So I'm gonna do as array of int.
And if that returns nil then I'm gonna turn empty array.
Okay. So if I have
never saved the diagnostic history to the defaults for
example, then this is going to come back nil,
okay, but I never have saved it before.
So we'll start out with a nice,
empty array in that case.
And also, if somehow some junk had got written here that
wasn't in an array of int for
some reason, then this would also be nil and
we would start out with a fresh array.
It would be kind of a weird case, but anyway so you
can see a simple way here to read and write from default.
Okay make sense, all right so now let's go run around and
see if this fixed our problem, of our defaults not
lying around, so let's see golden bear, dancing tree,
buckeye, put a whole bunch in there,
history it's remembering them all.
Golden Bear, 0, Dancing Tree, 100.
That looks quite awesome.
All right.
Let's try one other thing here.
Let's go try running this on an iPhone.
Let's see how this works on an iPhone, with our great new
feature here, and we'll see what it looks like.
All right so we got there a gold bear.
We got a dancing tree.
We got the buckeye.
Okay, let's see that history.
Whoa, that looks really, really bad, okay?
Well, hm.
So it didn't put up the history in
the little popover like that.
It took over the whole screen.
Modal, it's what a modal segue looks like.
And I put it up here, and
smashed into my carrier thing up here, and
there's no way to get out of here there's no done button or
dismiss or something, because in a popover we don't need to
dismiss because you just click on the background.
So you know, this is really a small amount of information I
could have put it in a popover there why did iOS adapt that
popover for the iPhone and put it to your screen?
Well, because it doesn't really know how big this is
going to be and how much data is going to be drawn or
whatever until it's being displayed.
And so on an iPhone to be safe it always adapts
popovers to make them full screen presentation like
this to take over the screen.
Okay, but in this case, we don't actually want that.
We dont want that adaptation behavior.
We want to prevent this adaptation behavior so
they just keep putting it in its nice little popover.
It'll be perfectly fine in iPad and
it will be perfectly fine for iPhone.
So, how do we prevent this adaptation behavior
from happening?
To do that, we need to get at that popover presentation
controller I was talking to you about in the slides.
And it's pretty easy to get ahold of it.
Inside our prepare-
So here's our prepare in our diagnosed,
diagnosed happiness view controller right here.
The same place down here where we're doing the preparation
happening, we can also say if we can let,
ppc I'll call it, equal the text view
controller's popover presentation controller.
So, this is a method in UI viewcontroller and
it'll return nil if you're not currently in the process of
being presented in a popover.
So if this segue if we changed this segue to
segue somehow else other than a popover,
maybe we wanted to go full modal for some reason or
we decided to push it on a navigation stack or
whatever then this would return nill and
so nothing that I'm gonna do right here would even happen.
So what am I going to do?
I'm just going to set the popoverPresentationControll-
er's delegate to myself, and that's because the popover
controller's delegate allows you to
have someone else control the way the presentation works.
And this is the first time you're seeing the [COUGH]
present the idea of a delegate in an action in an iOS.
Now you remember when we set ourselves as
a delegate you can see there's an error right here it says
DiagnosedHappinessViewContro- ller does not conform to
this protocol
UIPopoverPrsentationControlle- rDelegate.
And that's true, because up here we have to say we are a
UIPopoverPresentationControll- erDelegate.
Okay? And now,
once we put this on here, we have to go down here and
actually implement that method, the method we want.
And this method that we want is called
adaptive presentation style for presentation controller.
And this is basically saying, here's a popover controller.
[INAUDIBLE] You know how, in a delegate method, we
usually pass along the thing that's doing the delegation.
So this is that same popover presentation controller being
passed back to us.
And it's saying, please return a presentation style which you
want and when you're adapting on the iPhone.
So I'm gonna return the UI modal presentation style none,
which means don't adapt, Okay do not when you're on
iPhone do no adaptations do what you normally do,
which is put the pop over in a little window.
And that's it. That's all I
need to do to suppress that.
Now, by the way,
in addition to PPC delegating inside here, I could, there
are other methods in popover presentation controller.
You can go take a look at, and they will show you things that
you can find out about what's going on with the popover.
But setting its delegates so that you can control that
adaptation is a popular thing to want to do.
All right.
So let's go try it now on the iPhone again.
Here we go let's hit history and
now it's working okay coming up in the pop over here.
Let's go add history let's go another dancing tree over here
now we've dancing tree added there.
And it'll work fine landscape or portrait.
Questions about that?
All right.
The last thing I want to do with the pop over is
when we ran this pop over,
over here, you notice that it's kind of big.
It's covering the whole smiley face for no reason,
because it really only needs to be big enough to hold that.
Well, that's because really again the popover presentation
controller really has no idea how big this information is
in here.
And, but there is a way to tell it.
And if you think about who knows what the size of
this is best, well it's the text view controller.
Cuz the text view
controller's the one that's gonna display this.
It knows what it's preferred size would be.
So as we're talking about in the slides.
Let's go ahead and make it so
the text view controller reports its preferred size.
So I'm gonna go over here to the text view controller.
[COUGH] Now the prefered size is just a var in
UIV controller so the text view controller could set that
somewhere, it could just say preferred content size equals
something, but since this is a subclass UIV controller and
the content size would change every time this is changing.
And also might change depending on
how big a space the popover is being popped into.
We can actually do better here by overriding the var
preferredContentSize, which is a CGSsize.
I'm going to override it and do the get set.
Okay, so it's going to be a computed property,
get and set.
And on the setting side of this,
if someone set the preferred content size,
I'm just gonna let my super class.
Preferred content size do its thing, okay?
We'll just let the new value do that.
So I'm going to let my super class handle it or
someone sets it.
All right?
But if someone tries to get it, then if my text view has
been set, so if this outlet has been set, and if I'm in
the middle of being presented on screen, okay, then I can
ask the text view what its preferred size would be.
Okay, so we're going to let the textView do the work here.
So what does that look like?
So, we might say,
for example here, if textView does not equal nil.
Oops, I've got sticky keys on here, so
you see that in the lower corner there.
If textView doesn't equal nil, and if we're
being presented right now so how can we find that out?
UIViewController has another great bar
called presentingViewController.
The presentingViewController is the view controller that
is currently presenting you via some sort of segue.
So, in the popover case, it's going to be that diagnosed
view controller's gonna be presenting me.
But whoever it is, I can check to make sure that's not nil.
So, this is only gonna happen right here,
in the case where I'm in the middle of a presentation.
Okay, also my text here not to be no it's not clear that I
really need to set this because, probably my
outlets are all gonna be set before this gets there.
But just to be safe I'll set both of these things and
in this case I'm gonna let the text view tell me a size that
fits inside my presenting view controllers.
And this of course we will need to unwrap.
But it's okay,
cuz we checked to make sure it's not nil first.
So this is the bounds.size of our presentingViewController.
So in the diagnosedHappinessViewContro-
ller case, it's the whole seam, basically.
And we're just gonna see what is a good size that fits.
Now this is only a preferred content size.
So if this size that fits were really huge, for
example, the popover's still going to limit the size to
whatever its restrictions are, okay?
So we just prefer.
This is not actual content size, it's just preferred.
Now, what if we're not in
the middle of presenting right here?
Well, then once again I'm going to let my
super class do the work here so whatever it
would normally return I'm going to have it return.
So remember I'm overriding this my super class.
So really I'm just getting involved in
this one case where I happen to be in the middle of
presenting something, then I pretty much know what my
size is based on my text field okay?
So let's run and see how that fixes it.
All right, so the goal is to get our history, excellent.
Now notice also, our history was remembered even
after we quit our app and run it again because we are using
defaults which these defaults remember things when it quits.
So here we got 0, 150, 100, let's go back over here and
do nothing.
Looks good.
Let's go back and do Golden Bear.
Zero, so it's working beautifully there.
Okay, again it works no matter what size you use.
Go on there and it will also work on the iPad as well.
There we go.
So, there's the history.
Shows it up there.
There too.
Okay, so that's it for popovers, but we also managed
to cover a couple other things there along the way.
Most notably was the polymorphism of
view controllers.
And we were in our storyboard here,
we ended up actually creating a sub class,
DiagnosedHappinessViewContro- ller here to add some more
functionality, okay?
And that is not an edge case,
that's a common thing you wanna do.
You have some reusable happiness view controller or
something like happiness view controller.
You wanna use it, but you need to add something to it and
you don't wanna change it.
Well, that's exactly what
object oriented programming is for!
You can create a subclass of it and
add the methods that you wanna add to it, to your diagnosed.
And what's kind of nice too
is diagnosed view controller contains all the stuff that
has to do with the diagnostic business and nothing else.
So this is a very nice class well contained,
only has the diagnostic stuff in it.
Okay, so that's it, and you don't need this for
your homework per se, but there is an extra credit item
to add a popover so hopefully you'll decide to tackle that.
>> For more, please visit us at stanford.edu.
    You must  Log in  to get the function.
Tip: Click on the article or the word in the subtitle to get translation quickly!


Stanford - Developing iOS 8 Apps with Swift - 7. Multiple MVCs

3279 Folder Collection
Rong Ting Chang published on October 21, 2015
More Recommended Videos
  1. 1. Search word

    Select word on the caption to look it up in the dictionary!

  2. 2. Repeat single sentence

    Repeat the same sentence to enhance listening ability

  3. 3. Shortcut


  4. 4. Close caption

    Close the English caption

  5. 5. Embed

    Embed the video to your blog

  6. 6. Unfold

    Hide right panel

  1. Listening Quiz

    Listening Quiz!

  1. Click to open your notebook

  1. UrbanDictionary 俚語字典整合查詢。一般字典查詢不到你滿意的解譯,不妨使用「俚語字典」,或許會讓你有滿意的答案喔