Hi Alex here from rebeloper.com and welcome to another episode of
LBTAComponents Magic and in this one we are going to talk about how to cache a your
images, so without further ado let's get started!
Okay, now when you try to load a
lot of images into your app from a server you want them cached. What I mean
is that once you download them you don't want to download them again when the
collection view starts to show them all over again.
So for that LBTAComponents provides us a cached image view that we will use now.
So let's take a look at how we are doing in our project here. And I will just
simply build on the iPhoneX simulator here. And as you can
see these are all loaded from the device and they are from here from our Assets
catalog. Now we want to load them from the web and as I mentioned earlier I
have downloaded all of these images from idownloadblog.com and original Apple
wallpapers optimized for iPhonX. So if you want to check them out go ahead
and do so at this link. What I want to do today is to load these images into our
app from this site. And for example when I try to load this first
image I mean at this one it has a download URL. And if I right-click on it
and copy link address or I'll just simply click on it you will see that it
has this link to it. This is the download URL and this is what we
are going to use. So let's get back to our... let's see here our Datasource.
And then we are going to add here a new logic and that is instead of using this
image 1, 2, 3 and so on we are going to use our post structure with
an image URL. So for that lets go into Models and let's create a new struct I
will just comment out all of these and type in: let imageUrl. And we are going
to make this a string. And then let's initialize it with imageUrl it will be
of type string and self.imageUrl = imageUrl. Okay, now we have
our... If we build our project now we will have some issues. Now let's go over
well a few of them and let not start here we will start with
fetchUsersAndPosts. Now inside this function we will create a new urls
constant and it will be an array of our urls. And for now let us just use this
single one of the first image. Let's copy that out and let's paste this in here.
Okay, now we have an array with of course a single element and now "urls",
if I could spelled it out correctly. Now we can't
refactor this For Loop and I'm going to go like this: for url in urls. So we are
going to grab each and every element of our urls array. We are going to create a
new post and we are going to feed in our imageUrl, so the urls. And finally we
are going to add to our posts with append and post. Okay,
that is how you will feed this new array. And let's go over now let's take a look
at the other issues here. Now inside our DatasourceCell that is this cell here
we have an issue because we no longer have our post.imageName. And here we
need to construct our image with our imageUrl. And this is where
LBTAComponent cached imageView comes into play. So I'm just going to copy and paste
again this imageView. And I am just going to comment out for reference. And
let's start in here CachedImageView and the imageView needs to be
initialized as a CachedImageView. Okay, know once you have this because you have
imageView as a CachedImageView you can now access a very handy let's just jump
to our definition a very handy function and that is... let's just scroll down...
...loadImage with our urlString. And of course we may have an optional completion but
we will not use that at this moment. So what we need to do now is instead of
adding our imageView and let's just comment that out
we are going to construct it like so. imageView.loadImage with our
post.imageUrl and the completion should be an nil or we could just simply omit
it. But this is just fine. Now let's take a look at the other issues here yeah
when we pass on the image name to the large image controller, if you recall
then we just pass on from our image ProfileDatasources.posts imageName. So
for now I will just comment this out and let's just build and run and see, if we
do have one image cell posted there. And as it seems we have and we
will have to wait just a few seconds for this image to be loaded because it is
indeed a large image. Okay, till then let us just see what else do we
need to do. Let's go back to DatasourceController or maybe rather yet
Datasource. Okay, why we are not seeing any images and that is because here we
don't have a secure connection. And if we take a look at the log here... Let me just
go back here... it says app Transport Security has blocked a clear text HTTP
resource load since it is insecure. So as of I believe iOS 10 we need to have
secure connections to override this well use this only in development mode. You
need to add an app transport secretive allow arbitrary loads. And of course
again you should never use this in production apps because it is highly
vulnerable for outside attacks. So what you need to do here is go ahead and add
a new field and type in App Transport Security Settings. Okay,
and now just right-click on it and let me just open this up and add this plus
button and select Arbitrary Loads and set this to yes. Okay, this will do for this
development example. And now let us just build and run again and see what happens.
Hopefully we do get that image and yes we did get that image. Now let us just
fetch all of the images now and I have already set this up inside my test
project. And let me just find that list, here it is urls. And I will just simply
copy all 17 of them. Okay, let me just minimize that go into our Datasource
here and replace this URL. Okay, here we go!
Let's just build and run. Okay, here we go and we will slowly and get these images
loaded. Pretty good stuff! Now here is what I want you to really consider and
why you should use LBTAComponentes CachedImageView. And that is... let us
just make sure that we have only a one item here. So I just commented this out
and type in here: view.frame.width. And now we will
just have only one image per row. Let's just wait for that and as you can see
two images have loaded it. Let me just scroll down here and they are loaded but
as you scroll down they are loaded again and again.
Oh sorry I just clicked on that. And if we just scroll back again because the cells
are out of the collection views scope they should be in now again reloaded. But
since we are using Cached Image View from LBTAComponents these are no longer
needed to be reloaded. That is why they are cached and that is why this is a
very very helpful UI image extension, imageView Extension. Okay, and that is
very very important in terms of bandwidth and storage allocation. Okay,
what else do we need to do? Let us just go and make this again. Uncomment this so
we have three rows. And what else do we want to do let's just build and run and
see, if everything was as expected. And now that we have three images per row
you can see that the kinds of lags and till it launches well it it just fetches
those images it kind of waits a little bit. And for that we need to add
something for the user maybe an activity viewController or something like that.
And we are going to add that so let us just go into our Cells class and
UserProfileDatasourceCell and we are going to add
here an activity indicator view. So activityIndicatorView, let's just stop this for some reason it is not
responding. Okay, here we have our activityIndicatorView it will be of
UIActivityIndicatorView and let's construct it here... activityIndicatorView.
But before we do that let us just start animating. Okay, and now we need to
add this to our view so addSubview(activityIndicatorView) and let us just filled
with within our Superview. So fillSuperview( ). And one last thing is that we want
to stop this animation when we fetched our image so in the completion let me
just type that in again:" imageUrl" with "urlString: post.imageUrl" I believe
that is what we need. And here we will let's say... ...Okay and let me just type in
here activityIndicatorView.stopAnimating. So let's build and run and see
what happens. Oh of course we need to call it with self because we are inside
a closure. And here they are! They are loading and activityIndicatorView
is spinning around till they are all loaded. Pretty good stuff!
Now next up we want to finish off by implementing this logic that we want to
send this image to our large image controller and that is fairly simple.
Let's go back to I believe.. where is it?
It is in the DatasourceController and here in our didSelectItemAt index path we are
going to add our image name. But before we do that we need to know that we are
providing an imageUrl. So let's go to largeImageController and change some
things. First of all we should remove this imageName and add an imageUrl and
that will be of type String? and let's make it an optional. Next up we need to
change this imageView let me just copy it out and paste it down below here and
comment that out again and this time again we will use our CachedImageView.
Okay, let me just change that. Good stuff and now let us just go down here. Yes, we
need our load image changed and again I will just comment this out and create a
brand new function. Let me just give you some room here... ...and that url will be of
type String? and again it will be an optional. Okay, let's unwrap this optional
I'm sorry... ...guard let, let's type in here url and it will be a url esle
we are just going to simply return. And now what we need to do is load the image.
So imageView.loadImage and let's see with our url.
And finally we need to call this in our viewDidLoad. loadImageWithUrl and this
Url will be our imageUrl that we have just created, imageUrl. And now we need
to provide it in our DatasourceController. So let us just type in:
largeImageController.imageUrl = userProfileDatasource.posts[indexPath.row].imageUrl
Okay, and that should take care of it let's build and run
and see what happens here and hopefully we will get what we wanted and
we will have finally our finished app here. Okay, we are loading. Good stuff here!
And let us just step on any cell and we are ready. Okay, now that is it for your
knowledge of LBTAComponents of course you may add more sections or more
headers or footers and different kind of UICollectionViewCells but that
is something advanced and if you just take a look at the whole project that I
have set up here you can manage from here. Once again let me just show you
LBTAComponents is on GitHub and you can of course take a look at the
documentation maybe give it a start because it deserves it. And I really
enjoyed working with LBTAComponents all of the three parts of it:
The DatasourceController, The CachedImageView and of course our UIView anchor extension.
Okay hope you enjoy this video if you did go ahead and give it a thumbs
up and of course subscribe to the channels to see
more videos about awesome GitHub repositories and other iOS coding stuff
and as usual I will see you in the next one!