Bummer! This is just a preview. You need to be signed in with a Basic account to view the entire video.
Start a free Basic trial
to watch this video
The last thing we need to do before saving the photo is applying the filter to the larger image. Like with the display image in the last screen there are some considerations we need to make
-
0:00
The last thing we need to do here is apply the filter to the larger image before we
-
0:04
can save it.
-
0:06
The approach here is straightforward, but we have to make some tradeoffs.
-
0:10
This is something we keep coming back to but our image is pretty big.
-
0:14
Even at this stage, when we know which filter we want to apply, and
-
0:17
have a few seconds to carry out that operation.
-
0:21
In the time that we transition away from this screen,
-
0:24
to the time we hit Save at the end, it's not enough to apply the filter.
-
0:28
We can and will schedule the operation on a background thread but
-
0:32
at the current size that's still takes too long.
-
0:35
We don't need to update the UI right now.
-
0:37
So this filter operation can occur on a background thread and not block us, but
-
0:42
we do need it by the time the user hit Save.
-
0:45
So in the worst case, the user could just approach this screen, or
-
0:49
come to this screen where they add the tags and caption, and
-
0:52
hit Save immediately without bothering to add any of those.
-
0:55
So, we basically need to make sure this happens almost instantly.
-
0:59
The trade-off I'm going to make here is the same one we made earlier and
-
1:03
that is to use a smaller image.
-
1:05
Any other implementation would be far too complex and time consuming for
-
1:09
this course.
-
1:10
We've already spent quite a bit of time on this already.
-
1:13
Now, I'm not going to use the display photo because that's too small.
-
1:17
By too small, I mean with the way that the rest of our app is setup, we won't be able
-
1:21
to zoom in and out of these photos, and we still want to allow the user to do that.
-
1:26
We don't want to break an existing feature, just to add a new one.
-
1:30
Since we need to apply as soon as possible,
-
1:32
let's schedule an operation to handle it at the same time as we transition to
-
1:37
the photo metadata controller.
-
1:39
This way, we can be sure that we won't fire off any unnecessary operations
-
1:44
every time a user taps to check out a different filter.
-
1:47
Now, if we started immediately after transitioning to the current scene,
-
1:51
by the time the user is done entering a caption and
-
1:53
a series of tags, we should be able to process the filter in the background.
-
1:58
Let's define a function to handle this.
-
2:00
We laid the groundwork a few videos ago by defining an operation,
-
2:04
so we'll use the same approach here.
-
2:07
Func applyFilter.
-
2:10
Except this time we're going to accept a scaleFactor of type CGfloat.
-
2:18
Since we're going to use a smaller version of the image, we'll apply a scaleFactor.
-
2:23
Now the reason I'm making this a parameter is so
-
2:25
that it's easy to change and experiment with.
-
2:28
Okay, first we need to make sure we have a valid photo and filter to use.
-
2:32
So guard let image = photo, let selectedFilter
-
2:38
= filter else { return }.
-
2:42
Once we have an image, we need to resize it according to our scale factor.
-
2:46
Let's extract the width and the height of the image and assign it to two constants.
-
2:50
So imageWidth = image.size.width,
-
2:55
let imageHeight = image.size.height.
-
3:02
Then, we define a size by scaling these widths and heights.
-
3:06
So let size = CG size, and
-
3:10
the width is imageWidth times scale.
-
3:17
And the height is imageHeight times scale.
-
3:25
Now from there, we can use that custom method we defined earlier.
-
3:27
So we'll say guard let resizedImage =
-
3:32
image.resize to size, else return.
-
3:38
After that, you know the drill.
-
3:40
So using this image, we'll create an instance of filtration image.
-
3:43
So let filtrationImage= filtrationImage and
-
3:47
it takes an image so I'll paste in the resized one.
-
3:54
And then, we'll start an operation with this.
-
3:56
Let operation = ImageFiltrationOperation,
-
4:02
filtrationImage and selected filter.
-
4:07
Now for the completion block of this operation, we'll just assign the image
-
4:10
back to the store property, since we don't need to display just yet.
-
4:15
Completion block, if operation is cancelled,
-
4:20
then do nothing, when it is done self.photo =
-
4:26
operation.filtrationImage.image, okay.
-
4:32
The rest of this is busy work really since you know all of this.
-
4:34
Let's go back up to the top and define an operation queue so we can schedule this.
-
4:39
Let queue = OperatinQueue.
-
4:44
And the final bit is now to add the operation to this queue down here.
-
4:50
So, after the completion block we'll say queue.addOperation(operation).
-
4:58
We'll call this method applyFilter with a scaleFactor right in viewDidLoad.
-
5:02
So immediately after view loads, we'll go ahead and schedule it.
-
5:06
applyFilter, with a scaleFactor, right here, I played around for a bit.
-
5:10
And I think .25 is a decent scale factor that makes the image small enough for
-
5:15
the operation to complete quickly, and allow for some degree of zoom so
-
5:19
that we don't break our existing feature.
-
5:21
The bonus here though, with the way we've structured our logic,
-
5:25
is that if a user doesn't select any filter,
-
5:27
then this guard check will fail and we won't have to do any work.
-
5:31
In that case, we are going to have this really large image though.
-
5:34
Okay, let's wrap this section up by adding a save button, and a method so
-
5:39
that after entering all this information, a user can save a photo to disk.
-
5:44
Now after the applyFilter method, let's define another one.
-
5:48
So func setupNavigation.
-
5:53
So we need a saveButton in here which is a UIBarButton item.
-
5:58
And we'll use the systemItem initializer here because that has a default save.
-
6:04
The target itself and the Selector here is #selector
-
6:08
PhotoMethadataController.savePhoto.
-
6:15
Okay, let's add a placeholder for that method for now.
-
6:18
So @objc Func savePhoto.
-
6:23
We can't define this body just yet,
-
6:26
because we need to make some changes to our core data entities.
-
6:29
But this should suffice.
-
6:31
So let's go ahead and add this bar button item to the navigation item.
-
6:35
So naviationItem.rightBarButtonItem = saveButton.
-
6:42
And then we'll go ahead and
-
6:43
call setup navigation in viedDidLoad() right up at the top.
-
6:48
So that we actually have that save button.
-
6:50
And that brings our implementation of the photo metadata controller to a close.
-
6:54
We now have the UI and logic for the selfie portion of our app put together.
-
6:59
But we're still no closer to being be able to save it.
-
7:02
Over the next few videos, let's switch tracks from image processing
-
7:06
to modifying our CoreData models to accommodate this new information.
You need to sign up for Treehouse in order to download course files.
Sign up