Okay well, welcome to 
lecture 16 of Stanford CS193p, 
winter of 2015.
So today,
we're going to be talking 
about three major topics. 
One is the camera, how to 
 asically take a picture with
the camera or get video from
 the camera.
Then persistence which is an
important topic about how to
 store stuff in the flash 
memory of your.
Phone, and a lot of you have
already kind of dived into
this as part of your final
project, but I'm just gonna
 kind of give you a tour of the 
 various ways that can be done. 
 And then the last one is kind
of an interesting segway. 
I leave it for last because
it's kind of requires you to
be a little bit of a visual
thinker, to see what's
happening when we do it, but
it's called an embed segue,
which is where we basically
take one MVC. 
And we embed its view into
another MVC's view hierarchy
which is kind of fun.
So let's dive in right in to
 the camera.
The camera is accessed via
 this file or 
this class called UI
ImagePickerController.
It is a UI view controller,
 sub-class actually of UI 
 navigation controller, I 
believe.
And it's very simple to use.
You really just configure it
and
then you put it up modally.
 Okay?
 So there's really nothing more 
to it than that.
We learned about how to put
things up modally last time
with presentViewController.
That's all you're gonna have
 to do. 
So, the process of using the
UI image picker controller
to get something from the 
camera, 
 is, you create it, and you set 
its delegate. 
It won't do anything without
its delegate, so
 you have to set its delegate.
Then you're gonna configure
 it, for you know?
 Do you want just still images
 or video, or 
that kind of stuff? 
Do you want users to be able
to edit the pictures they've
taken before? 
They import them into your
app, etc.
 Then you just present it with
presentViewController.
 And then you're gonna respond
 to delegate methods that tell
you, okay, I took a photo,
here's the image data,
or the video, the URL of the
video, that the user took.
So that's pretty much it. 
 Each device. 
 Kinda has different hardware,
 although that's becoming less
 and less true as the years go
by.
 It used to be that there were
some iOS devices that didn't
even have a camera at all.
 But certainly there were early 
on iOS devices that could.
 Do still images, but couldn't
do video for example.
So as with all the hardware
 things, whether it's you know, 
core motion or any of those
 things we always wanna ask and 
see what we can do first. 
So it's very easy for the 
 image picker controller it has 
a class function called, is
source type available.
And there's three different
sources for images or
video to come into your app.
 One is the camera, obviously.
 Another one is the saved 
photos album, 
 that's essentially the camera
 roll.
Right, things that they've
taken with the camera.
And then there's the photo
library,
which is the same thing they
see in the photos app, okay.
So you can kinda pick which
one of those things.
You wanna get your image or
video from and
they're a little bit
different.
 A little bit of photo library
and the saved photos album
 are treated pretty much
exactly the same, but
the camera is a little bit
different in how
 it's presented, so we'll talk
 about that in a moment.
 Once you know your source type 
then you're gonna say,
what are the available media
types, image or video.
Or both.
 Now it's almost not even worth 
checking for image anymore.
 Because if you have a camera,
it can get an image.
So, I think it'd probably be
okay if you just never even
called this available media
types for source type,
camera if you're trying to
get.
An image, okay, because it's
gonna be there.
But if you wanna get video,
you definitely should call
this in case someone has an
 older iPhone that won't, 
doesn't capture video.
 Now these two types, the 
kuTTypeImage and
 kuTTypeMovie, which are
basically strings that
 specify these two media types. 
Strangely, they come from 
 this.
 Framework that your otherwise
never gonna import which is
 the mobile core services 
framework.
 So if you wanna use those two
types right there or
two constantsKUTType images
and movie.
 You need to import mobile core 
services.
 Okay?
I'm kinda lingering on this
 one because this is some 
people forget.
 And they're just like what the 
 heck?
Because if you search in the
documentation it's kind of
hard to find. 
That you're supposed to do
 this.
Whatever.
 So I made a special slide and
emphasize it there for you.
 You can obviously ask UI 
inventory picker controller
for more detail even than 
 this.
Is there a camera and what
kind of things can it take?
 You can say, is there a front
camera? 
 Is there a rear camera?
Which you might care if you
 have an app that's like selfie 
oriented.
 It might wanna know that 
 there's a front camera.
For that.
 And you can also tell whether
a flash is available on that
 device, etc. 
So there's a bunch of class
functions and 
UI image picker controllers.
 You can find out what's going
on.
 So here's the code, typically, 
to prepare to present the 
picker. 
You're going to create the
picker. 
 You're gonna set its delegate. 
 You're gonna ask if the camera 
is available. 
 If it is, you're gonna set the 
 source type to be the camera.
 Then you're gonna ask and see
 if, for example in this case,
I wanna take a movie with my
camera. 
 So I'm gonna ask is that 
 kuTTypeMovie available.
Now, this line of code right
there, if availableTypes as
 NSArray).containsObject(kuTTy- 
peMovie.
 That's kind of a weird line of 
 code.
Really, it doesn't. 
 Fit into the swift world very
 well.
You just do it.
I's an old objectice C based
API.
 And kuTTypeMovie is even kind
of an older kind of string
even than NSString. 
And, so.
 We kind of have to do this old 
 style thing. 
I'm sure probably somewhere
 they'll probably come up with
some new API for this whole
 camera thing that doesn't have 
this old stuff, but for now
you have to do that.
And then you just tell the
 picker the media types I want
 the user to be able to take is 
just a movie, so
 in this case they wouldn't be
able to take a still image,
they would only be able to
take a movie, if you.
 Pass an array with just
kuTTypeMovie. 
So that's it. 
You've configured the picker
now, you just need to
present it with that present
view controller.
There are some other things
 you can kind of configure with 
the picker before you put it
up.
One is editability. 
That's whether you're gonna
 allow the user to crop.
The image or edit the video.
 There's actually a video 
editor built in there
that they can edit the video
 before it returns to your app. 
 You can also limit video 
capture, for example,
to be lower resolution if 
you're just doing something
that's gonna be in a little
 square somewhere in a webpage, 
you can go low resolution.
 If it's something that.
Maybe it's going to be
 Airplayed to a high resolution 
 device or something like that, 
 and you can go for 
a higher resolution.
 And of course high resolution, 
 you're gonna use more memory.
Etcetera, etcetera, okay? 
You present using view
 controller.
Now, the thing about this is
interesting is
 when you're doing the camera.
You're always gonna present
view controller.
 It's always gonna be take over 
the screen even on the iPad.
 So on the iPad when you do the 
camera, 
you're gonna have this huge
camera taking picture.
 Okay?
The whole screen is gonna be
 the camera.
However, on the iPad,
 if you're just looking at the
photo library, okay?
 Or the camera roll you want to 
present that in a pop over.
It's only gonna be fairly 
 small, 
like the 320 wide by I don't
know how high.
 600 or something.
So that's really something
you're supposed to put in 
a popover.
Now an iPhone, it doesn't 
matter. 
In both cases it's gonna be
 full modal,
take over the screen.
 Okay?
Cuz it's just too big to put
any other way on the iPhone.
 Okay?
So, you present this thing,
and it sits there on screen,
and then, when the user use
this photo, okay, or
 use this video, this is gonna
be called right here,
this delegate method: image
picker controller did finish
picking media with info, and
with info dictionary there,
has the results of what they
did.
 And when you get there,
we'll talk about what's in
 there in a minute. 
 But when you get this and you
get your image, or whatever,
then you wanna dismiss this
 thing. 
And I've kind of put here a
line of code, 
 presentingViewController.dism- 
issViewControllerAnimated.
 Usually you're not putting the 
presentingViewCcontroller in
there, because you are the
presentingViewController. 
 You just presented this thing. 
 So you wouldn't need that part 
 of it. 
 But I just wanted to emphasize 
that again, you dismiss by
 sending a message through the
presentingViewController, 
which is probably gonna be
you.
And you'll see in the demo,
 we're gonna do this, and 
 we're just gonna call dismiss
directly.
We don't have to say
presentingViewController. 
The other delegate method 
you're gonna get of interest
 is image figure controller and 
d cancel.
 And that means they hit
cancel. 
So now you don't want to use
 the image that they were 
 taking, whatever.
 So in that case, you just need 
 to dismiss, 'kay?
So that's it. 
Those are the two delegates
methods you get.
So let's look in that info
 dictionary,
see what's in there.
All kinds of stuff in there.
 There is the image they took,
obviously,
if they're taking a still 
 image. 
 If you allowed editing,
 then it's gonna have also the
edited image like cropped,
 right, if they picked a
different space of it.
 Also if they cropped it, 
 you'll get the rectangle that
they chose inside the thing.
If it's a video,
then you're gonna get this
media URL, okay.
 It's just gonna be URL to some 
file somewhere in your
 sandbox, which I'll talk about 
sandbox later today.
 It points to the video, 'kay?
When you get this image or
 video you might wanna save it. 
We're gonna save it in our
demo to a file in the file
system cuz I wanna show you
how the file system works.
 But really, most likely, 
you're gonna save it to the
 device's photo library, 'kay?
 That probably if someone takes 
 a photo and you wanna save it, 
 that's likely where you would
store, you might store in 
 the file system but more like
in the photo library,
 you do all that with this, I'm 
not gonna for time reasons,
cover that, but.
 You an check out this class's
ALAssetsLibrary, it's pretty
 straightforward how you access 
 the assets library, and
you can put things in the 
photo library there.
 By the way,
 the UIImagePickerController is 
kind of an old API, 
 it's a simple way to get 
things with the camera, but
there's a whole, much more
powerful API called 
 AVCaptureDevice, especially if 
you're getting video,
you might wanna check into
 that.
It's kind of a more powerful
 way to do the stuff that 
the UIImagePicker can do. 
 So I'm not gonna cover it, but 
just so 
you know that it's there. 
 If you're just getting simple
image, or just a simple clip
of video, you're okay with
UIImagePickerController, but
if you wanna do more with 
that, then AVCaptureDevice.
The last thing about your 
 ImagePickingController is that 
 it does support putting
overlays.
So when that camera is on 
screen and
the user's trying to take a
picture,
 you can have your own controls 
 on there, your own buttons or
whatever you want, using an
overlay view. 
The camera is always full 
 screen, of course, so you need 
to make sure that the view
that you're putting overlay,
 you know, matches up with that 
screen's bounds,
which you can get using the
 UIScreen classes bounds. 
You might have your controls
 actually have the take a photo 
button. 
 In which case you might wanna
hide the Take a Photo button
that comes with the camera,
 and you can do that with 
showsCameraControls equals
 false. 
And then it won't show its
 Take a Photo button, but 
then you better provide one,
because you won't be able to
take a picture otherwise. 
And then finally, you have
this cameraViewTransform. 
Normally, the camera maybe
takes a square picture, or
 it might take its picture, in
 any case, if the aspect ratio
 doesn't match the aspect ratio 
of the screen, but you might
want it to basically take a
 full, you know, basically take 
the piece of it that is the
aspect ratio of the screen.
And you can do that by
controlling the transform of
the cameraView.
So AffineTransform there, 
remember,
AffineTransforms are scale,
rotation.
 In translation, so 
 you can do the scale there to
scale it up if you want to.
Let's do that, all right. 
All right, so that is the 
ImagePickerController,
 let's go ahead and go back to
our tracked demo and
 use the ImagePickerController
to make it, so
that if we have a waypoint,
one of our custom waypoints
 that we now can edit, that we
can add a photo,
 just by taking a picture with
 the camera, okay?
That's what we're gonna do
 here.
So let's go back to tracks.
Here we are in tracks.
Just remember where we are
 here.
We've built this thing that
allows us to click on
the map and then we can see
 the images.
And we can also drop a pin.
 And when we click on the 
little detail disclosure, 
we bring up this little new
controller right here,
 where we can edit the name and 
the info.
So what I wanna do here is
actually use this nice big
 space we have at the bottom of 
our editor to show and
 edit the photo, okay that goes 
along with this waypoint. 
 Now, you might think the first 
 thing I'm gonna do here is go
 down to my object palette and
 grab an image view, down here, 
but I'm not gonna do that,
'kay, and
I'm gonna show you kind of a
little bit of an interesting
 trick about ImageViews.
 One thing about ImageViews is
that they have an intrinsic
 size.
They're like labels.
They want to be the size of
their image, okay, for
auto-layout purposes.
 They strongly want to be that
 size.
You have a question, sorry.
>> [INAUDIBLE].
>> No, I'm not.
 Close. 
Let's see here, close.
 [INAUDIBLE]. 
 So you guys are only gonna get 
it from, starting from here,
cuz I'm not gonna go back to
the start.
I'm [INAUDIBLE]
 much.
 Okay, so if I have auto-layout 
and I drag an image view in
there, then when I set the
image, it's gonna wanna make
the auto layout huge because
the image is gonna be big,
especially if I have a high
resolution photo, so
I don't want that to happen,
I want this image view to be
 the size I say it's gonna be.
Basically I want it to use
whatever space is available
 and no more. 
So, well,
 kind of a cool way to do this
is to use a generic UIView.
 So, instead of taking a
UIView, 
 I'm gonna pull a generic 
UIView out here.
 Now, by the way, when you put
a generic UIView out,
sometimes it's hard to see
what the heck is going on 
because it's white on white.
So a lot of times when I do
that, I think I might have
mentioned this before, I'll
just set it to some other 
color for a moment, so that
while I'm editing it here in
the storyboard I can size it
 and set up its constraints and 
all that stuff, and I can 
kinda see what's going on.
 Okay, so let's put this thing
 in reasonable spots over here, 
 let's set some constraints for 
it, put some vertical
spacing to the top there, 
trailing over to here,
this guy over to here, and
I'll put this one down to 
the bottom, and we used to
 have a constraint
on this one to the bottom 
which we want to get rid of.
Where is that?
Bottom of space to bottom 
layup, it's this one.
And, we could also, while 
 we're here,
make sure this is standard
 value, 'kay? 
So that look's good.
 This guy also standard value.
All right.
So, we've got this UIView in
here, and really what we're
gonna do is put the 
UIImageView inside of it. 
 And I'm gonna manage it
manually.
So I'm gonna size it to the
right size
that I want in code, okay?
And that way, it'll never be
 trying to fight the auto 
layout system to make things
 really big,
 and smash other things off the 
screen, or
make my popover really
 gigantic, or things like that. 
 'Kay?
So, let's go ahead and do 
 that.
Gonna go over here. 
 I'm gonna go back, 
 this is our editable waypoint
view controller,
the view controller for this
 whole thing. 
So I'm gonna go down here,
 let's create a new little mark 
 for images.
 Okay.
 So this'll be our image
handling area right here. 
 So I'm gonna control drag from 
this generic view out here.
 This is not my ImageView, this 
is my, what did I call this,
container?
Yeah, ImageViewContainer. 
 Okay, this is going to be just 
a generic UIView, see,
that contains my image view.
 And so my image view is
actually gonna be something
here that I create in code.
I'll just say equals
UIImageView, actually.
 Okay, so there's my image view 
and on my didSet here,
when this thing is set, I'll
go ahead and put that image
view into this thing by just
 saying image view controller,
add sub view. 
Image view, capitalize this
for me. 
 Okay, so I basically just put
 that image view in there and.
 Let's see, what's the problem
 here?
 It's, oh, imageViewContainer,
yeah, thanks. 
ImageViewContainer, too used
 to typing in controller. 
Let's make this bigger, too,
by the way, so
we can see what we're doing.
 Okay.
So, everyone see what I did
 there? 
 I just created this generic UI 
 View,
 I put the image view in there. 
I'm gonna have to manage the
size myself, though.
 I'm not gonna do autolayout in 
 there, et cetera.
 And, basically, I'm just gonna 
always set the image
view inside to be the right
 aspect ratio for my image, but 
no wider than my container
 view.
And if my overall controller
gives me no space for
the view image, then I don't
get it, okay? 
And also anytime my image 
changes I'm going to ask for
more space by resetting my
 preferred content size.
Remember preferred content
size for the pop over?
And so I'm going to ask for
 more space.
 I may or may not get it. 
Cause pop over might be near
the edge, but I'll ask for
 it and we'll see that code in
just a second here. 
 Alright, so I got that.
 Here is some code. 
 Let's put some code in here to 
do that.
I have this extension that I
added to my way point
controller and it has this
method update image.
 Now update image, the reason I 
 snippeted this in here instead 
 of typing all into you've seen 
it all before, right?
I'm dispatching to another
thread, 
I'm getting the image data.
Here I'm getting the URL and
 getting the image. 
I'm dispatching back to the
 main thread, 
I'm setting the image in my
 ImageView so 
this is just not worth our
 time to go through this again. 
We've done this two or three
 times. 
 But I am calling this function 
here makeRoomForImage, and
 all that makeRoomForImage is,
 it sees if the image is
 any bigger than the last image 
we had. 
And if so, it updates the 
preferred content size to 
give it a little bit of a 
extra height. 
 And this extra height might be 
 negative if we just set
 the image to nil, for example, 
it might try to collapse it
back down.
So again, this is just
pertaining to what we prefer
our overall content size to
be.
And if we can get this space
then my generic UI view that
 contains my image is going to
 get bigger.
And there's going to be more
 space for me and I can make my 
UIImageView bigger, see more
 of my UIImageView. 
 Okay?
So that's it. 
So we do need to update this
 image. 
 We'll do it in updateUI, 
 right? 
So we have updateUI up here
 that updates the text fields,
so we also wanna update our
image there in that as well.
Okay, so that's it. 
That's how all that's
necessary here to display 
the image in my view
controller and
keep it's size contained. 
So let's go ahead and kinda
put a test image into our 
edited waypoints just to see
if this is working. 
 So I'm gonna go back to
GPXViewController and
 where I add a waypoint here by 
 dropping I'm gonna 
say waypoint.links. 
Let's append. 
I'm gonna append a new GPX
 link,
 that's the thing that has the
reference to a URL, 
to the image or whatever and
so we'll do http
CS193p Stanford images
panorama.
 Okay.
I'm just picking one of the
ones we had there at random.
So, now this waypoint has a
 link, okay?
Just like the waypoints that
came out of that GPX file,
they have links also.
One other thing we're gonna
 need to do is over here in our 
MK GPX right here, our
 EditableWaypoint.
Right now, it gets its
thumbnail and 
image URL by looking them up
by this type thing. 
Thumbnail type, large type.
And just for the purpose of
the demo, I'm gonna make it
 just return the first link in
 its link list of links.
 So let's go down here and just 
say return links.first.URL.
 And then we'll have the
 thumbnail be the same as 
the image URL, so it won't
have a separate thumbnail.
I'm just kinda cheating this
really quick so
 that we can see some image in
our UI. 
 So let's go ahead and run this 
and see what happens this is
 for, oh we got, what do we got 
 here, oh sorry override, 
 we gotta override these. 
Override.
Override.
 Okay.
All right.
 So I'm gonna run this here, in 
the simulator.
We'll switch the device in a
 second here. 
All right.
So here we are.
 You all remember this UI I've
got here.
And I've got these images on
the left, for there.
 So I'm gonna go ahead and drop 
one for 
an editable waypoint here.
 So I'm gonna click on it, you
can see.
And there it is, there's our
panorama.
 See, I used that as the
 default image, and 
if I click our editor here,
 there's panorama, it appears.
Okay, so, that's kind of fun
and
 notice that that's a very wide 
 aspect ratio, but it only made 
enough space to do that, and
 so we can edit it. 
 So, now we want to be able to
 change this view.
We don't want it to be
panorama.
I only just showed that to
 show you how this would work.
So we need to go back to add
some UI,
 some button that lets us take
 a picture with the camera and
put that here instead.
Okay, so that's what we're
going to do now.
Let's go to our storyboard
 here.
 I'm gonna put that button like 
right here, I think.
 Let's move this over a little
bit and 
I'm gonna put it right in 
 here.
 I have a nice button for that, 
 or image for 
that with the camera.
So, let's go ahead and
get a button. 
 Okay.
Here's a button.
 Okay so we'll put this button
right in here.
Okay I'm going to set this
image to be that camera, so
let's go ahead and drag that
camera image into our
 XC assets, so here's our image 
assets. 
Drag this guy in here.
 Okay.
 We could put higher resolution 
versions in, et cetera, but
we're just gonna use that.
So let's go to Button here.
I'm gonna go to the button
here and change its image to
be the camera, and I don't
 want the word button on there, 
okay, so here's my button.
 Now we'll do some auto layout
 here, to get this thing, 
in here.
 So I will put this up against
this edge.
Let's put something between
here the horizontal spacing.
 Let's have these two be center 
Y.
We had another one in here
 that we'll have to delete now
because we used to have this
thing on this edge, so
let's go find that. 
 That's trailing space to super 
view right here.
We'll get rid of that.
We'll make these to be
 standard spacing right there.
 All the rest of it looks like
it's standard,
 must have lined them up
perfectly there.
 Any problems, oh, horizontally 
ambiguous?
 Okay.
 So this guy wants to hug, the
button wants to hug itself
 because this guy's willing to
be as wide as we want.
It doesn't want to hug down
but this one does and
the system has to know who
gets the space there.
So now the frames will be 
different.
 Okay let's go down here, 
update our frames make sure
everything looks good.
It does.
Okay, excellent.
So we've added this little
 button to our UI.
So now we're just gonna have
 this button. 
When we click it it's gonna
bring up the camera.
So let's go do that.
All right, I'm just gonna 
 control drag from this button
right here, and here.
And it's gonna be an action,
we'll call it Take Photo. 
That's what it does.
And we don't need any
argument, or anything.
There's Take Photo. 
 So, in here. 
All we need to do is create
that picker and present it.
 And then we're gonna implement 
those delegate methods and
we'll be good to go.
 All right, so what do we need
to do in here?
 First I'm gonna check and make 
sure I have a camera.
 Actually I'm gonna, first I'm
 gonna go and 
give us some space to work
 with.
All right.
 So first I'm gonna check here, 
and
see UIImagePickerController.
 If I have a camera available,
so
I'm gonna say source type 
 available camera.
 Okay?
So if I have a camera,
 then I'm gonna set my picker's 
 source type. 
 To be the camera.
 Okay?
What else have we got?
Oh, sorry.
 I've got to create my picker.
 So here I'm gonna say let the
picker equal UI image picker
 controller.
So when you create it, it's
 just parentheses, parentheses, 
 you don't have to specify any. 
 X-ray information when you're
 creating it. 
So now I've set the source
 type.
Now here I would maybe, if I
was doing video.
 You know, I would check media
 types to make sure that media
 type is available. 
And then I would say
picker.mediaTypes equals. 
And then the types I want.
So, in this case I just want
 image only.
 Okay?
 And then we obviously need the 
 picker to set its delegate to
be self.
 Okay?
Without the delegate this 
thing does nothing. 
We could also set some other
 fun things here like maybe we
allow editing.
 True?
So we'll see what that UI 
 looks like.
 And then we can just present.
ViewController.
 The picker.
Animated?
Yes.
And, we don't wanna find out
 that a capture has 
 been put up. 
And, what else do we got in
 here?
Oh, okay.
So this is the famous, oh.
Where does this coming from?
So, we have to come up here.
Import MobileCoreServices.
 That takes care of that. 
And this one of course is we
don't implement.
UI Image Picker Controller
Delegate.
 Okay, let's do that, UI Image
Picker Controller Delegate.
 Now what's interesting here is 
that we still have an error
once we put this UI Image 
Picker Controller Delegate
 thing here.
It says.
 Wave point controller does not 
 conform to UI navigation 
controller delegate.
 Why the heck does it say that? 
 UI navigation hasn't got 
anything to do with that. 
Well that's because the UI
image picker controller is
a UI navigation controller,
inherits from it, and
they use the same variable
delegate.
To be their delegate.
So, we also have to come up
 here and say that we are a UI
navigation controller
 delegate, even though we don't 
actually implement any of 
 these methods in the protocol. 
 That's fine. 
They're all optional.
 Okay?
So, that's a little tricky
thing sometimes people don't
understand with the picker,
but.
You definitely need to do 
 that.
 So, that's all that's required 
 to put that picker on-screen,
 so it's gonna be on-screen and 
 now we just have to implement
 those delegate methods.
 So, here they are. 
 This one, by the way, is 
 deprecated,
don't use that one. 
Here is the one where they
pick something, and 
here is the one where they
cancelled.
 Okay?
 So let's do the one where they 
picked. 
Something, so 
 I'm just going to say that the 
 image they picked is the info, 
that info dictionary that's
 being passed along here. 
And there's a bunch of
 constants in 
UIImagePickerController, and
 one of them here,
 ImagePickerControllerEditedIm- 
age, so 
 that's the edited image, and I 
wanna get it as a UIImage.
Okay, because this info is,
AnyObject is the value, so I
have to cast it here.
If I couldn't get the image,
 okay, the edited image,
then I'm gonna just try and
set the image equal to the
unedited image, which is the
 ImagePickerControllerOriginal- 
 Image. 
 As UI image. 
Now you might say, why am I
 doing this line of code right
 here because I'm clearly 
allowing editing up here. 
Yeah, we're allowing editing
today but
if I some day just said, eh,
 I'm not gonna let people edit
and I change this to false,
 well, all of the sudden, 
this code would break if I
 didn't have this nice little.
 Thing here.
 So I'm thinking ahead a little 
bit to make it so that
 a change somewhere else in my
code won't break me here. 
 Okay?
And so I've got the image.
So I'm just gonna set the,
 my image views image equal to
 that.
And I'm gonna make room for
it.
 Okay, that's this
makeRoomForImage that I told
you I added down here.
 Okay?
And that's it.
I've got everything, so I'm
just gonna dismiss. 
And notice, I'm not saying,
presenting view controller
dismiss here. 
Because I am the presenting
view controller.
So I'm just saying, dismiss
 true.
And completion.
 Okay?
We have to do the same thing
here for the cancelled case.
 Okay?
But in the cancelled case,
 I'm only gonna do this dismiss 
 right here, okay?
 Obviously, I'm not gonna grab
 the image or 
 anything if they cancel. 
All right?
 So let's take a look at this.
Let's look at this, let's go
on iPhone 6 plus here.
 There it is, okay? 
Actually, let's go. 
 We still have our little 
panoram in here.
 Let's go to that really quick. 
 That's over here.
 So we'll just go back here and 
 we'll comment this out.
 So that if we're testing again 
 in the future we can go
 back to it.
All right.
But let's get this code back
 up on the screen here so 
you can see it.
 All right, so here's our photo 
 stuff. 
All right, so 
let's run again.
 All right so I'm gonna drop a
pin.
Notice that we don't have an
 image right here.
 Okay?
 It took away that little test
 image. 
And clicking our edit thing
and
 we've got this big space now.
There's that big grey box 
 right there because I set that 
UI image in my storyboard to
be grey.
 Right? 
So let's go look at that. 
See over here, this is gray.
 So really, when I'm shipping,
I'm obviously gonna go here,
and
 set this back to its standard, 
which is clear basically. 
 Okay?
 Back to our code.
All right.
So we're gonna take a photo
 here.
I'm gonna press that little
camera. 
Okay, camera. 
And you can see camera comes
up right here.
 And this was helicopter
skiing. 
 So let's look at our favorite
hat.
Ski hat, we got our favorite
ski hat.
It's R2D2.
Actually it's better than 
 R2D2.
There a little San Francisco
 Giants R2D2. 
 Okay, so we're gonna take this 
picture.
Okay, so we can now crop it.
 Okay?
 We could zoom in on the really 
important part.
All right?
 And then we can say Use Photo, 
and it comes back and
 it appears in our thing here.
If we take a different
picture,
maybe if we decide, okay, we
 want the whole hat, all right, 
we'll zoom out there, and 
we'll use that photo.
We got it, okay?
Now, of course, this is not
going to save this, so
 as soon as I go away and come
 back, it's not there and 
 that's because we need to save 
 that picture somewhere.
And we're gonna save that in
 the file system with our 
next demo.
Let's take a quick look what
this looks like on the iPad.
Make sure that it works over
there as well.
All right.
So, we'll drop a pin here.
We'll go there.
Bring up our little popover.
 Take a photo, again we get the 
 huge size screen.
 We'll have to do front facing
camera, 
 because I got it on this 
 thing. 
Here we go, this R2-D2 hat
 there. 
 There we go. 
All right.
And there it is.
 And so we can put it into our
little popover,
which is kind of fun.
 And because we have that 
generic UI view, and
 I asked for a bigger preferred 
content size, it made some
 more size and then the generic 
UI image view got bigger. 
 And so then I was able to make 
the image view inside of it
bigger. 
 Okay.
Excellent.
Okay, let's go back to the
 slides, and
 learn a little bit about 
 storing stuff, and 
then we can come back and 
 store that image.
All right, so there are a 
number of ways to make
 things persist on your device. 
In other words,
some data that you want to
live forever on your device.
 Okay.
 Even as your application 
 is quit, the phone gets
 powered off, 
 whatever, you want that stuff
to exist.
So I'm gonna talk about four
different ways.
You already know one,
actually,
which is NS user defaults.
 Okay.
That's a really simple, kind
of small amount.
 This is for bigger data, these 
 four things. 
 The first two, I'm just gonna
 really, briefly pass through.
I'm barely even gonna talk
 about them.
 Because, really, you're
 certainly not gonna use them,
I don't think, in your final
project.
Maybe some SQL master out 
there will be doing some SQL
 thing. 
 But I don't think anyone will
use that.
But then the File System and
 Core Data, I know a lot of you 
are doing Core Data as your
final project.
And that's a great, 
 not covered in lecture thing,
 by the way.
Even though I'm gonna talk
about it today,
 that doesn't mean I'm covering 
it in lecture,
I'm barely gonna talk about
it.
But, so I know I lot of you
are doing that.
 And some of you wanna use the
 File System, also. 
You're reading and writing
files from the File System.
So hopefully, this will get
you up to speed there.
 So let's talk about Archiving. 
 Archiving is a way to store a
 graph of objects,
 okay, on to disc.
And those objects don't have
to be property lists.
 So they don't have to be 
 array, dictionary, date, 
whatever.
 Because that's all we can put
in NSUserDefaults, right? 
 And NSUserDefaut is for small
things. 
But if we want to store big
 things, bigger object graphs,
and we want a lot more
 flexibility. 
Well, that's where we use 
Archiving.
 And, Archiving can archive any 
 tree of objects as long
 as all of them implement these 
 two methods, 
encodeWithCoder and an init
method that reads themselves
back in from a coder.
So encodeWithCoder basically
writes them out,
writes themselves out,
basically as a dictionary.
Okay, and then encode, and
then init will instantiate
the object when it gets read
back in,
reading that stuff from that
 dictionary.
So where is this used?
Your storyboard is archived.
So all the things in your 
archive,
all of those ui views, all
those ui view controllers,
 they are all encodable.
Okay, they implement this 
 NSCoding protocol. 
 And they all get written out.
 Basically, when the storyboard 
is saved, this whole object
graph, the entire thing, all
the buttons, everything in
there gets written out using
this Archiving mechanism. 
And that's why we have that
 weird init thing with UI view
controller and UI view where
there was always this
required init coder thing.
That's because they 
 participate in this Archiving. 
 Now, I would not recommend to
you if you had a graph of 
 objects, you know like, I want 
to make them persist.
I think I'll archive them.
 I wouldn't do it.
I would use one of the other
mechanisms I'm gonna talk 
 about today. 
 Okay, this is really is great
for story boards and
it really is the right thing
for story boards but
I'm not sure that for
arbitrary data storage if it
really makes a lot of sense.
 Okay.
 All right SQL, some of you are 
database experts and
 there is SQLite on the iPhone. 
SQL is for those of you who
are not database experts, 
 SQL is basically a programming 
 language for databases.
 Okay, for creating tables and
columns and rows and
tables and all that.
And you can, if you have a
bunch of code lying around
 that you had to write to a SQL 
database,
then you could certainly use
SQLite. 
And the next thing I'm gonna
talk about, or
 the thing I'm gonna talk about 
 the end here, Core Data, 
 it uses SQL underneath, okay.
It's writing all its data to
 an SQL database as well. 
 But probably not gonna access
 it directly. 
The interface,
the programming interface to
 SQLite is like a C API.
 It'll work in Swift cuz Swift
 has compatibility with C APIs. 
 But it's a little hard to use
cuz it's gonna have 
weird things like, you know,
 pointers into memory and 
things like that, that Swift
doesn't really,
 it has ways to adapt to this.
So that you can do it, but
 it's not really native,
it's not part of Swift's way
of doing things.
So it'll be a little odd for
those of you who are used to
 Swift, to try and program this 
SQL API using Swift.
But it can be done. 
And I'll have to look up how
to do it.
All right.
So the last two things I'm
gonna talk about is 
 the File System and Core Data. 
So the File System is very
simple, okay. 
 Your device, your iOS device,
has a Unix filesystem.
Okay, because I told you the
 very first day of this class,
 basically Unix is underlying a 
variant of Unix,
 BSD, Mac is underneath all of
iOS,
 it's providing the kinda core
 OS services. 
So you have the Unix
 filesystem there.
 And if you want to store 
things in the File System,
you just store them in this
Unix filesystem.
Now, kinda four steps to do
 that.
One is you have to get the
root path, it's true,
 some URL, file system URL, not 
HTTP URL,
 that you're going to write or
read from, okay.
 So, you basically got to start 
 somewhere in the File System.
Now, it's a Unix filesystem,
 of course it starts at slash,
 but you can't write in slash,
that's the, you know, root
directory.
You have to write somewhere
 down, slash, slash something,
slash something, slash
something,
 that's where you get to start. 
So finding that root path is
 the first step and 
 we'll show you how to do that. 
Then you're gonna append the
 path components onto that URL. 
 So, if you want to create some 
 directories in that place and
 then some files, you're gonna
be using appends and
NSURL has some methods to do
 that.
 And then you're going to read
 and write files from that URL. 
And we'll talk about how you
do that.
And finally, you're gonna 
manage the filesystem.
 You might wanna remove a file, 
 you might wanna rename a file, 
 you might wanna see what files 
 are in a directory, and
that's all done with this 
class, NSFileManager.
 Okay.
So that's it. 
This is how the File System
 works. 
So let's look into all of 
 these steps. 
So you see this File System,
it starts at route. 
 It's a protected file system,
though, so
you can't see most of the 
 stuff that's in root, or 
 any of the system directories
 or whatever. 
It's not readable by you. 
So, there is a part of the
 Unix filesystem there, though, 
that is your application's
 own, it's called its sandbox.
Okay, and this is the only
place you can write.
 Some of the places in your own 
 sandbox, you can't even write. 
Like the place where your 
actual application is,
you can't write there.
So you can't modify [LAUGH]
 your own code by writing 
 something in that directory or 
something.
Okay, but many of the
 directories, 
subdirectories of your
sandbox, you can write in.
 So this is the place where you 
can write, and
you can read everything in
your sandbox. 
 Then we'll talk about how you
 get a URL into your sandbox in 
a second.
Now, why do we do this
 sandboxing thing?
 For obvious reasons, for 
security.
You don't want to be able to
 look into other apps and 
 see what's going on over 
there, and you don't want to
be able to access the system
directories and
mess up that iPhone.
So it's completely obvious,
but there's one
 slightly non-obvious reason to 
this sandbox, 
is that since everything you
are ever going to write on
the local disk is in this 
sandbox.
If the user deletes your app
you know, they go over here
 and hold down until the thing, 
it's the other one. 
Which one are we showing? 
Yeah, this one.
 See them wiggling there? 
 So, if they hold down wiggle,
if they were to press x to
delete it, it would delete
your entire sandbox.
So everything you've ever 
written is gone.
 Okay?
 Also, that's true for backup.
 If they backup their phone to
 iTunes U, okay, or 
iTunes and iTunes U, iTunes,
 then it would back 
 up certain directories in your 
Sandbox, not all of them. 
 Okay?
So, that's another reason to
 have this Sandbox. 
So, what's in there?
What's in the Sandbox?
 There's various bundles, which 
are directories.
 There's the application bundle 
I talked about,
that's where your actual app
is, okay?
 And everything there is
read-only.
 All your storyboards in there. 
 If you have JPEGs that are in
 your image assets, 
they're all in there.
They're all read-only.
 If you put something in there
you needed to edit, 
like maybe some SQL database
or
 something you put in there or
some data file.
 You would have to copy it out
 of the application bundle into 
 one of these other directories 
in your Sandbox, and
 then you could edit it there.
 Okay?
 So, you can ship your app with 
 things you're gonna edit, but
 you just have to copy them out 
 of your application directory. 
And then, there's also other
directories in there.
 The documents directory, 
 that's where you should store
what the user perceives as
 their data, okay?
The things they're creating
and editing and
 owning that they expect to be
there all the time. 
Even if you don't, kind of,
divide it up into a document
 in your UI, it's still,
that's what the documents 
 directory is for.
There's also a caches
directory.
This is for data that you 
 could throw away.
 So, it's some information you
got from
the Internet that you can go
back to the Internet, but,
 it might be slow to go to the
Internet, so you're going to
keep a local copy, but, you
could throw it away.
That directory, for example,
wouldn't get backed up
to iTunes, okay, if someone
 plugged their phone in,
because they figure you can
 recreate it, okay? 
 And there's a bunch of others, 
there's about a dozen
different directories.
 And, you find all these
directories by looking
in the documentation for the
term NSSearchPathDirectory.
 Okay?
 And, I'll talk about that in a 
second as well.
 So, how do you get the URL to
these special 
directories in your Sandbox?
 You do it with this file 
manager class,
this NSFileManager. 
Now, NSFileManager, there's
actually a class
function called,
DefaultFileManager, 
 that will give you the default 
NSFileManager.
 The only thing to be a little
careful about that one is,
 NSFileManager is thread safe.
 And a lot of times, you might
want to read and
write a very large file in a
 different thread.
 Okay?
And NSFileManager is
 completely thread safe,
 but only for 
 an NSFileManager instance that 
is created in that thread.
In other words, you should
 never create an NSFileManager
instance in one thread and
then use it in another one.
 That's not thread safe.
 Okay?
 But, even if you're accessing
the same files,
trying to remove or look at
the same directories,
that's all perfectly fine,
 as long as each thread has its 
 own NSFileManager. 
So the NSFileManager
DefaultFileManager, 
you'll see that in the
documentation.
 That one is kind of your main
thread, DefaultFileManager.
 If you're only gonna use it on 
the main queue,
then you can use that one.
Otherwise, just create an 
instance.
It's pretty light-weight to
create an instance of
 NSFileManager just like this,
 okay,
let fileManager equal
NSFileManager().
 So, once you have a file 
 manager, then you can send it
 this message, URLsForDirectory 
inDomain.
And that will tell you, it
gives you, actually,
 an array of all the documents
 directories, 
all the caches directories,
all the application bundle
 directories. 
Now, why is this an array?
 Well, on iOS, it doesn't 
matter. 
 There's always only one thing
 in this array, okay, and 
that's the user's documents
directory,
 the user's cache's directory.
 And that's because on iPhone,
 you only have the user's 
resources.
 But this API works on a Mac as 
well, and on the Mac,
you might have the user's 
document history or 
a cache's directory.
 You might have the computers,
and then you might even have
 the networks, okay, the local
networks.
 That's why you might get 
 multiple of these. 
So, don't be freaked out by
the fact that this returns
an array of NSURLs, there's
always only going to be one.
 You can just use the first one 
in there.
 And, that is going to be a URL 
that points to this kind of
directory like the documents
directory, or 
the cache's directory, or 
whatever.
 And, you specify which one you 
 want with that first argument, 
NSSearchPathDirectory.
And, you have to go look in
the documentation and
 see what the special names of
them are.
 But there's, like, 
NSDocumentsDirectory,
 NSCachesDirectory, 
NSDocumentationDirectory. 
By the way, be careful with
 NSDocumentationDirectory 
versus NSDocumentsDirector.
I can't tell you how many 
 final projects people post in
 Piazza, and they'll say, I've
been trying to write to my
 NSDocumentsDirectory for days
but it says not writable. 
 And it's because they've been
 trying to write to 
 the NSDocumentationDirectory,
which is read-only. 
Okay, that's documentation
that ships with your app. 
 So be careful with the escape
 completion there,
NSDocuments is the writeable
one,
 okay, NSDocumentation is 
documentation.
All right?
So, now you have the URL to
 the root of one of these 
things, like the document's
directory,
the cache's directory.
And, now you want to write
some files in there.
Well, you're going to use 
URLs, NSURLs methods,
URL by appending path
component, or 
URL by appending path
extension.
 Some extensions like .jpg, or
whatever, .doc,
got some document format of
some sort.
And so, that's how you're 
gonna do that.
And, by appending multiple
path components,
you can build things inside
directories, right? 
 So I can say a path component, 
 today's documents. 
And then path component foo,
 and that would be a directory, 
 today's documents, and inside
foo, okay?
 So that's how you build up the 
URL.
So, once you have a URL, you
can find out some things, 
 like, about it, like, is this
a file URL, or
is this a network URL?
 Sometimes, you wanna know that 
 because you're accessing 
an image, and you wanna know
 whether it's on disk or
whether it's on the network,
 you might put one in the 
thread. 
Cuz some people ask,
 should I always access my file 
system in the thread?
And the answer is, probably
for
small files unless they're,
 you know, megabyte size files. 
 You're probably fine to access 
 them in the main queue.
It's pretty fast, that flash
memory, 
pretty quick at getting the
 information back.
 You probably don't need to do
 that.
 It couldn't hurt, especially,
if you already have 
 the code to deal with the fact 
 that file might be over
 the network, might as well do
it for the local file, too.
 There is also a very important 
method that's a little bit
buried in the documentation
 called resourceValuesForKeys.
This is how you get things
 like,
 when was this file last
accessed?
 'Kay?
 How big is this file in bytes, 
 'kay?
 That's this NSURL thing, 
resourceValuesForKeys.
When you give it the keys,
 like files last change date or 
whatever, and it's going to
 return in a dictionary,
rather, with those keys you
 gave and the values for
 all those things, 'kay?
Permissions, all that stuff.
ResourceValuesForKeys.
All right, now, I've got a
URL,
 I want to to write to the file 
system. 
How do I write something to
 the file system given the URL? 
And the answer is usually,
you're going to use NS data,
 okay?
Might use the property list
ones, like NSArray and
 NSDictionary and write a 
 property list out to it. 
But you oftentimes can use
NSData, cuz you have some 
 image data or some other data
you want to write out,
 sound files, something.
 And so, you do that with 
NSData's method writeToURL,
 atomically.
And so, writeToURL, you just
give it a URL.
It will write that file out
 there. 
And the atomically means, 
 write a temporary file,
 and then, remove the old file, 
and
put the new one in an atomic
 transaction. 
 Okay?
 That way, if something happens 
 in the middle of writing 
the file, the file won't be
half written. 
 Okay?
It'll be always a completely
written file. 
And it'll return a Boolean,
as to whether that was
 successful.
 Okay?
So, that's the primary way
you're going to write.
That's how we're gonna do it
 in the demo. 
That's the number one way 
you're going to write.
 I told you that NSFileManager
could do other things, too,
manipulate the file system,
create directories, 
 things like that.
You're gonna have to look at
 the documentation. 
 There's quite a few functions
in there.
 It also has a delegate.
Where it'll let you control
things. 
There's like, should write
file at path. 
Something along those lines
where it's basically shoulds
that you can control whether
 something happens. 
 And, so you can look all that
up on documentations really,
it doesn't make sense for me
 to go over it all here.
 >> [COUGH].
>> Okay, so that's the file
 system, and
I will be demoing that in a
 moment in Tracks.
 But first I want to talk about 
Core Data,
the last persistence thing.
 How many people here are doing 
Core Data for 
their final project?
Wow, okay, so half of you.
That's great. 
I'm really, really, really
 happy about that,
cuz I didn't teach Core Data
 in detail this quarter.
So I was hoping a lot of you
would do it as your 
final project.
Cuz Core Data is actually an
 important thing to know. 
Not just as a way to store
data but
it's just conceptually
understanding a little bit
 more about how iOS works, and
 things like that.
Core Data, if you can figure
out how to do that, 
then you understood a little
more about how iOS works. 
So for those of you who are
not doing Core Data, I'll go
through this quickly since
 most of you are doing it, but
 what is Core Data? 
 It's basically a way to store
your data in a sequel
 database, basically, but in a
totally object oriented way.
 So you don't have to issue any 
 sequel commands or 
anything like that, create
rows and tables.
 It's gonna create all that for 
you.
It's completely
object-oriented API.
 It's a very powerful framework 
in iOS. 
It has a lot. 
 Most of you are getting it for 
your final project, 
 even though you're only going
to touch the basic thing of
setting properties and
 creating entities. 
But there's a lot of really
 powerful querying things that. 
 >> [COUGH].
 >> Can happen in there.
 Most of the things you can do
with SQL, you can do up in
the Core Data layer, things
like optimistic locking and
 all that stuff is all doable,
so
it's a pretty powerful
mechanism.
 It is backed by SQL, but 
 it can also be backed by other 
things. 
XML, or you could even
actually get involved and 
store the data in your own
 format, but
that would be very advanced
 usage. 
So how does it work?
 How does Core Data work, 
 you create this visual mapping 
in your schema.
 Okay, it's not like the parse
that you saw at the Friday
section a couple weeks ago,
 that's schemaless. 
It's basically creating its
schema on the fly, right? 
 It creates the rows and tables 
as you ask for them.
 This one you define your 
scheme upfront.
What are going to be your 
objects,
and what are going to be the
object's properties on those
objects.
 And then basically tables are
kind of like classes if you
 want to think of it that way.
And then the columns and the
 tables are kind of like vars.
Okay and then coordinator 
provides a way to have these
@NSManaged vars, where
 literally you just set the var 
and it's gonna be go set the
information in the database,
 and of course you can query on 
 all this stored data as well.
You create the schema with
this visual map.
 You do new file and you create 
this thing data model.
You're gonna get this thing,
it kinda looks like this. 
 Okay?
It's a graphical, piece of
 graph paper looking thing, and 
 you can actually create things 
that look like class like 
photo and photographer here.
And then you can create the
columns in the database, and
then you can create 
relationships by controlled
dragging between them.
So you're gonna create your
schema totally
 graphically there. 
 Then you get this
 UIManagedContext.
That's kind of your handle,
your hook, on your database.
There's a couple different
ways to do that.
 There's some code that can be
 generated when you create your 
 project, you can click on the
 Use Core Data button and 
it will create this code for
you in your app delegate, 
 and then you will have a 
method in your app delegate
called manageObjectContext.
 Now you have a handle to your
 database and 
 you can start creating objects 
 in there or
 setting the values of things.
There's also another class,
an important class called 
 UIManagedDocument, 
it's a way to encapsulate a
Core Data database, okay? 
 What's really cool about 
 UIManagedDocument, if you use
data approach versus the Use
Core Data approach, 
 is that the iCloud side of it
becomes a lot easier.
 So if you wanted to have your
core database work on
 iCloud so that I could see it
on all my devices, and
it would be automatically 
synchronized, 
 then you wanna use 
 UIManagedDocument. 
So maybe some of you.
Anybody trying to use
 UIManagedDocument? 
 'Kay, so that is kind of like
the next step 
 you would think about doing in 
Core Data.
All right, so once you have
this context, 
 the handle on the deck,
 on this core database, you can 
create objects.
You do that with this
NSEntityDescription class 
method called 
 InsertNewObjectForEntityForN-
 ame, and you're basically just 
specifying the name of
the table, which is like a
class, and
you give it the
managedObjectContext, and 
 it will create a new instance, 
 okay, a new row in that table, 
to use the database 
 terminology. 
And it's gonna return to you
 this NSManagedObject, or 
 subclass thereof.
 And it's with this 
 NSManagedObject that you 
can set the columns, set the
values in that row. 
You can also fetch, 
 you create these things called 
NSFetchRequests.
They basically specify what
you're looking for, 
 pretty powerful predicates in
 there for saying,
 well I want all things, all of 
 the rows whose column is 
called name starts with the
letter a.
 You can do that kind of fetch
request and then you issue
 the fetch request and you get
 it back as an NS Array.
This fetched object thing 
 would be an NS array, or 
 an array, of NS managed
object. 
 Okay?
 And so that's kind of what you 
 can do with a database.
Once you have these objects,
 these NSManaged objects, 
 you can use these two methods, 
the setValueForKey and
 valueForKey to set and get the 
values in there.
Or even better,
you can create subclasses of
 NSManaged objects. 
 That have these apps on
NSManagedObject vars, and 
Core Data will automatically
make it so
that if you set that var, it
 sets it in the database. 
 And if you get that var, 
 it'll fetch it from the
database, okay?
So, you use normal SWF
 notation for that. 
Okay, so that's kinda what
 Core Data's about in its core. 
 Pun intended, no pun intended. 
 Core Data is also really good
 at hooking up to table views.
 Cuz you can imagine you've got 
these big tables of data in
 Core Data, and it'd be nice to 
have a table view that is 
displaying all the rows or
 some subset of the rows based
on some query.
In the table view, and so 
there's this class called 
 NSFetchedResultsController in
iOS, a super simple class.
It basically, you give it a
 fetch request, and 
 you associate it with a table
 view, and then that table view 
will always show what that
fetch request would fetch,
even if the database changes
 out from under it. 
'Kay, cuz you add something,
and
the thing you added matches
that fetch request, boom, 
it will just automatically
appear in the table.
 'Kay, so you don't have to be
doing all, basically,
the FetchedResultController
 will implement all of your UI
table of your data source 
methods for you.
How many rows in table, how
many rows in section.
 Give me the self or own index
 path.
You have to do your own self
or
own index path to do the UI
part of it, but
there's one method in the 
FetchResultsController that
will tell you which managed
object is in this row,
in the table. 
So if you're doing Core Data
for your final project and
you're doing table views, 
 you definitely want to look up 
NSFetchedResultsController.
 Okay.
All right, so the demo that
I'm gonna do, 
 I'm not gonna demo Core Data,
don't have time for that. 
So I'm just gonna demo the
 file system piece. 
And we're gonna do that by
making our waypoint.
Store the image that we took
with the camera as a JPG in
the file system.
And then we'll have a URL to
it,
we can update the waypoint.
And our new edit away points
will work just like the ones
 that come in a GPX file. 
 All right, so what do we need
 to do to do this?
 Really, all I'm gonna do here
when I take a photo, okay,
 and the information comes back 
in the delegate,
 I'm just gonna say 
SaveImageInWaypoint.
 'Kay, remember that this NBC,
its model.
Is the waypoint that we're
editing.
So, I'm just gonna have a 
little method here, 
saveImageInWaypoint.
 So let's implement that, 
saveImageInWaypoint.
 And all we're gonna do here is 
 we have the image, 
 we already got it, put it here 
 in our UI view image, so 
 I'll just get it out of there. 
 And we're just gonna write it
in the file system and
then we're gonna update the
waypoint to use that URL, 
simple as that.
 So, if we can get that image,
so
 if our imageView has an image. 
 Okay?
Because they could be nil.
 It might have been set to nil
by some means,
then I'm gonna get the image
data as a JPEG.
 And the way you do that, 
there's this cool function,
UIImageJPEGRepresentatio and
you just give it a UIImage.
 Okay?
 And you give it a compression
quality.
So, I'm gonna do really high
 compression. 
 Okay?
So this is a quality between
zero I think, 
which is like the most
 compressed you can do to one,
 which is like almost no
 compression. 
 Okay?
I think that's the direction
 it is, 
I hope that is what it is.
 But anyway, so you can look at 
the documentation for it. 
 But we're gonna turn our image 
here
 into by doing this in NSData.
 So this is going to return in
NSData. 
 If we look at the up here, see 
that is NSData.
 So, it's gonna turn our image
 into NSData. 
It's kinda the opposite of
 NSData contents for URL, 
 which is the opposite it would 
take the URL for
some data and turn it into
UIImage.
This goes back the other way
for JPG.
So, if we're able to do that
conversion, then I'm
 gonna get the fileManager here 
as a local variable.
I could just constantly, I
could use the defaultManager
 by defaultManager you see I'm
in the main thread. 
But just in case I ever put
this in a separate thread or
something, I'll go ahead and
use an instance of it here.
 So now I need to get the 
documents directory,
 because these waypoints, 
really, 
the user perceives them as
their document data.
 That's where you would want to 
 store this.
 It's not like a cache that we
can't ever get back.
 We need that photo if we lose
it.
 It's gone forever. 
 So, and again, we might really 
want to be saving this in 
 the photo library. 
But I'm just trying to demo
 here how to do the file
system, so that's why we're
 doing that.
So, I'm gonna get the
 documents directory and
 so here's a nice long line of
code for you. 
Take the fileManager, we're
gonna get the URLs for
directory.
 Okay?
The directory we want is the
DocumentsDirectory and
 the domain always on the 
iPhone is the UserDomain. 
 More space please. 
 The UserDomainMask here. 
 Okay?
 So that's gonna get this array 
 of URLs and
I'm just gonna get the first
 one out of there.
 Okay?
And then I'm gonna make sure
that it's cast to URL.
So, if all of this succeeds,
then I got
the documents directory and
what did I miss here?
DocumentsDirectory. 
 There we go. 
 Okay?
So this will end up being a
NSURL that
points to the 
 DocumentDirectory. 
 Okay?
So now I have a
 DocumentDirectory, 
 I need a unique name for this
 photo that I just took.
So, I'm gonna create that by
 just saying, 
 NSDate.TimeIntervalSinceRefer- 
enceDate.
So this is just a certain 
 number of seconds. 
 This is just a unique number.
 It's gonna be a double.
That unique identifies this
photo, because it can't have
two photos taken at the same
 instance in time.
So we got that.
 And then so
I'm gonna let the URL for my
 photo be the docsDir and then
URLByAppendingPathComponent
 and then I'm just gonna create 
a string out of that unique
 and we'll say that it's a jpg. 
 Okay?
So now I've created a URL,
which is just this unique 
string with JPG on the end.
 So now, if I can get the path
 to that URL. 
 So this is gonna take the URL
and
turn it into a string, okay?
 Cuz URLs are in this URL 
objects.
 I want the string, you'll see
why in a second here.
If I can get that, then I'm
 gonna take that ImageData and
write it out to that URL and
 I'm gonna do it anatomically.
 Okay?
And if that succeeded,
 if I was able to successfully
do that,
then I can add it to the way
 point by saying, waypointLink. 
 And I'm just gonna replace all 
of my waypoint
links with a GPX.Link, which
is href of that path,
the string version of the 
 NSURL. 
 Because GPX.Link, it's a 
generic GPX parsing thing.
It takes strings, it takes
URLs as strings here.
 Okay?
Everyone understand all this
 code?
 This is typical code for 
writing something out into
your file.
 So come into your Sandbox, in
this case,
 the DocumentDirectory of 
Sandbox.
All right.
So let's go ahead and run 
 that.
It's good being
on the iPhone here. 
 Okay.
So let's drop a pin here and
 can see that we have our 
dropped there and we have no
image yet, so 
 let's click on our little eye
here and get an image.
So, I'm going to click the
camera. 
Let's get a picture of our
R2D2 hat here.
 There we go. 
And we'll use that photo. 
And now we have our image.
We can even, for example, 
 change our title here maybe to 
let's say, R2SF.
All right?
And click Done.
Now, if we click on our pin,
we can see that the image 
 has been saved and we can see
it there on the left.
 We can even click on it, 
scroll around on it.
 Okay?
Or go back and edit it and
take a different photo if we
wanted to.
[SOUND] Okay. 
Now by the way, to make this
work I had to make a small
change to the code, which is
right here and
 didSelectAnnotationView. 
 We just want to make sure that 
if we have no call out
 accessory, because we started
 without one when we drop a new 
pin, like this.
 We have no image and so, 
it didn't add the left call
out accessory in that case.
 So just when the annotation's
selected,
we're just gonna make sure
that it adds it.
 Okay.
Back to our slides. 
All right.
 Okay.
So the last thing is Embed
 Segue ways.
So, Embed Segue ways is just
taking the view,
 self.view, basically of an MVC 
and
putting it in another MVC's
 view.
 Okay?
So, it's basically embedding
one MVC into another.
It's a pretty powerful
 encapsulation technique. 
The way you do it is really
 easy.
 In the storyboard, 
you just drag out this thing
 called a container view, okay? 
You drag the container view
out.
It's gonna be a little view
and
it's gonna have a little MVC
attached to it.
All right.
So, it looks like this when
you drag it out.
That little grey thing's the
container,
 that's the thing I dragged out 
from the storyboard.
And then that little arrow
there moving, 
 that's the Embed Segue.
 And you can see there's
 another MVC there and that MVC 
 is the one who's self.view is
 gonna be embedded. 
All right?
 The timing of this, you've got 
to be a little careful on 
 prepareForSegue, because this
embed all
 happens before any outlets are 
set as usual. 
And so, it's happening very,
 very early in the game.
 So, usually in our Embed 
 Segue, 
what we do is we grab onto
that MVC.
 Okay, so that we have a handle 
 to it. 
 We can talk to it. 
 We can prepare it, set it up,
whatever want later.
 So this is best shown by just
demonstrating it so 
 I'm gonna demonstrate that by
going to tracks.
And here's our tracks UI, so
 tracks right here. 
This is our map view right
 here.
 And when we click on the left
edge of a call out, 
it brings up this UI image
view controller.
Right, which is currently 
 fully contains an image. 
And what I'm gonna do is I'm
gonna embed in the corner,
 a little rectangle down here,
 a little square that contains
a little map view, with just
 the pin for this image.
So that when I'm look in the
 image, 
especially on the iPad where
I've got a big screen,
I can see some context of 
where this image was taken.
 Right? 
 So I'll see them both on time. 
So I'm basically gonna embed
another view controller into
this guy right here.
 So what do we need to do that? 
The number one thing we need
 to do when we have an embedded 
 view controller is we need to
 do this segue, and 
we need this view controller
 right here to have 
a little subclass to manage
 that.
So right now this view
 controller, as you know, 
is an image view controller.
So if we select this,
 you can see that its class is
ImageViewController.
So I need to change this. 
 I'm gonna change this to be a
waypoint image view 
 controller.
 Okay?
 So a waypoint image view 
controller's gonna be
a subclass of 
ImageViewController.
So it's gonna do everything
this one does.
 Plus it's gonna know about how 
to manage that embed.
 Okay?
So let's create a new class.
All right, the Cocoa Touch
 Class. 
It's gonna be a subclass of
ImageViewController,
one of our classes. 
And I'm gonna call it
WaypointImageViewController.
 Okay.
 Put it in the standard place.
'Kay here it is, here's our
WaypointImageViewController.
This
WaypointImageViewController,
its model is the waypoint.
 'Kay?
 This guy's model, did everyone 
remember what 
ImageViewController's model
is?
 It's just an image URL.
 Right? 
 So we need a little more 
powerful model here in our
 WaypointImageViewCcontroller,
so
I'm just going to have var
waypoint.
It's a GPX Waypoint.
It'll work with the editable
ones or non-editable ones.
 And when that waypoint is set, 
 I want to make sure that I set 
 my super classes model.
 So, I'm gonna say my imageURL
 equals that
waypoint's imageURL.
 Okay?
So, here,
 I'm basically setting my super 
 class's URL there. 
And what are we getting this
 about here?
Oh, okay, we're not there,
 okay.
 And then I'm also gonna set my 
 title equal to the waypoint's
name, might as well.
 And them I'm just gonna update 
 my embedded map, okay, because 
 the whole point of this guy is 
he has this embedded map. 
 So, we'll have a function here 
 called updateEmbeddedMap, and
 it's going to update that map. 
 And we'll talk about how 
that's going to happen
a little bit later. 
This isn't optional, that's
why, okay.
 All right, so that's it. 
So that's our waypoint image
 controller,
 kind of its main thing.
So now we need to go back to
our storyboard, and 
 I'm gonna make this image view 
 controller right here be 
a waypoint image view
 controller.
So I'm just gonna go here to
its identity and
 go down here and say now it's
 a WaypointImageViewController. 
 Also, I'm gonna fix this 
 segue. 
This is a segue from our map
 view.
 I'm gonna just fix this one to 
prepare this guy by giving
his way point.
So that's over here in our
 GPXViewController, 
down here in prepare.
 Okay, here's where we're 
preparing
 the ImageViewController. 
 Okay?
So here I'm going to say, 
if I can let the waypoint 
image view controller equal
the segue
destinationVewController, 
contentViewController as a
waypoint view controller. 
So in other words if it's a
waypoint image controller,
then I'm gonna say waypoint
 image view controller waypoint 
equals my waypoint. 
And actually I'll just go 
ahead and
 leave this other code in here
 as an else.
Else if it's not a waypoint
view image controller,
 it's just a normal image view
 controller,
 we'll still make that work as
 well.
 But we could delete this code, 
and it would work fine now.
But I'll just leave it in 
there, just for reference.
 Okay.
So now we need to go do this
embedding business. 
 Okay.
We need to put this thing in
 here.
 Now one thing I'm gonna advise 
you to do, when you're doing
embedding, and kind of be a
 little careful of. 
Is when you drag out this 
Container View,
which is at the very bottom,
 by the way, it's gonna want to 
be a subview of the thing 
you're dragging it on.
 So it keeps trying here to be
 a subview of that scroll view, 
and I don't want it to be a
 subview, a scroll view,
because I want it to sit on
top.
Okay, I want it to always be
there, and
the scroll view is scrolling
behind it.
 I don't want it to be in there 
 scrolling around.
 Okay?
 So it's really a bit of a pain 
to do that with this in way.
 So you can just take something 
like your scroll view, for
example, and move it out of
the way temporarily.
 So I just moved it out of the
way.
 So now I can put my Container
View in here. 
I can put it where I want,
 probably not 
in the very corner there, 
something like that.
I can do all my auto layout
 here.
 Maybe we'll do this a little,
do it higher, yeah, 
let's do that, bottom space.
Probably, I want this
 container to be a fixed width
 and height, okay.
I don't know what width and
height I would want.
Maybe like, I don't know, 
let's say 200 
by 200, sorry, double-click
 there. 
So let's make it 200 by 200.
 We could make it whatever size 
we thought was kind of most
appropriate for this space.
And then we could put this
back, this scroll view back.
By the way, if you go over
 here to the document outline,
you can see the order in the
view hierarchy.
 Like this would be behind, and 
 this is in front of everything 
 else.
 Okay.
 Scroll view the activity 
 indicator in 
this Container View.
Now, I dragged this in here,
 but if we look oh, 
 look at down here. 
What's this guy?
 Okay.
See that is the little view
controller that could.
 This is the little view
controller that is going to,
 whose self.view is gonna be in 
 here.
So let's do this guy right
 here, and we need a view 
 controller class for this, so
I'm going to create that. 
This is gonna be the world's
 simplest map view controller.
I'm gonna call it, in fact,
 SimpleMapViewController. 
It's gonna be a
 UIViewController.
 And all this 
SimpleMapViewController is
 going to do is to make its map 
view outlet be public.
So that other people can do
whatever the heck they want
 with the map view that's 
inside of it. 
 So let's put a map view inside 
 of it. 
Let's go back to our
 storyboard.
Get this little guy right 
 here.
 Okay, I'm gonna, first of all
I'm gonna make him be
a SimpleMapViewController,
like that.
And then I'm going to put a
map view,
 which is right here, inside of 
him.
 Okay?
Let's go ahead and go,
suggested constraints.
Probably, that'll be just 
fine, yep,
all looks good to me.
And so let's just create an
outlet for that.
Whoops, get an outlet here,
small screen, there we go,
 okay.
Whoops, 
 SimpleMapViewController, 
 there it is. 
 Let's Ctrl+drag here, mapView, 
 'kay?
So that's it. 
 That's the entire
 implementation of this class.
 It's just gonna do that. 
 It does MapKit, so we have to. 
Import MapKit, okay, so this
 just is public and 
we can do whatever we want
with this map.
 So, what do we want to do with 
this map?
 Well, we want this map to show 
our waypoint in our 
waypoint image view 
 controller, okay?
So, that's how we're gonna
update this embedded map. 
 We're, can access the map view 
directly.
 But, the one thing we need to
do, first,
is we need to do this segue
 right here.
 So, we need to give this segue 
an identifier.
We'll call it the Embed Map
 segue. 
And we need to prepare this
 segue. 
 And we prepare it here.
We're going to prepare it by
just by grabbing that map 
 view, okay?
Grabbing that controller, 
actually,
 than grabbing the map view out 
 of it. 
So, I'm gonna prepare for 
 segue here.
 I'm gonna say, if the segue's
 identifier equals, 
and we'll just, no constant
 here.
We should do one, but we're
not gonna do. 
So, it's the embed segue. 
 Then, actually, I'm just gonna 
 create a var here, 
 which is the SMVC, the simple
map view controller.
Which is a
 SimpleMapViewController, 
optional.
And, I'm just gonna actually
 set it inside this prepare for 
segue, so, smvc equals the
segue's 
 destinationViewController as a 
 SimpleMapViewController. 
So, in the set prepare for
 segue, 
I've just grabbed onto this
 SimpleMapViewController. 
 So, now that I have it, okay,
 let's go ahead and 
 update our embedded map here,
and let's do the code for 
 doing the embedded map.
 Very simple. 
I'm just gonna say, 
 if I can get that map view out 
of that smvc. 
Okay, then let's set the map
view to be mapType Hybrid.
And, then we want to set the
 map view's annotations.
 So, let's remove the existing
 annotations from the map view. 
 And then, let's MapView.add an 
 annotation for our way point.
 Okay, which remember, is an MK 
 annotation, so we can do that. 
And then, let's also zoom in
on those.
So, showAnnotations, the map
view's annotations and yes,
we want it to be animated.
 Okay?
So, that's gonna update our
embedded map. 
Yes, Embed Map.
 Okay.
 All right, so, now that we're
 actually embedding the map and 
 doing that actual prepare for
 segue, 
we should get this to work.
Here we go, and sure enough,
 there it is. 
 And, it's kind of hard to zoom 
out.
 Actually, I'm gonna do this on 
 the actual device
cuz it's a little easier to
 pinch. 
>> [INAUDIBLE].
>> Oh, I didn't hit Play. 
There we
go.
All right.
 There we go. 
Here or there.
 We should have our nice image
 here.
 And inside here, this MVC is a 
fully operational MVC.
 It can be pinched. 
It can scroll around.
 It does all the things that it 
 would normally do. 
So, we can actually see that
we're in
the Greenbush area of
Greenbush Lake, all right?
Okay, and if we rotate or 
whatever,
a lot of layout works on it,
et cetera.
 Okay?
So, that's embedded segue.
Sorry to run a little bit 
 long.
If you have any questions,
I'll be here as usual.
