Hey everybody what's going on this is Caleb with slopes dot com.
And in this video we're going to set up search Fisi and it's table view the X way we're going to use
our X swift hardcore in this video.
And we're basically going to set up our search bar to be able to cause our table view to react to the
data that we're passing into it.
And as we enter search queries or characters we're basically going to be able to make API calls download
all the data and return it to our table view which is really really cool.
So pull open that X code project close the assistant editor and let's go ahead and let's head into search.
VC we've got a lot to do.
So let's get started.
So first we need to of course import our swift.
OK then we need to import our X cocoa so that we can use it with the table view.
We also we're going to need to import Alamo fire.
And yeah let's go ahead and now that we have those imported Let's start by setting up our dispose bag
which is a pretty common way of doing things.
Var dispose.
Equals dispose bag.
All right.
So now we've got to dispose bag.
That's awesome.
Let's go ahead and let's write a function that's going to be our binder function that we're basically
going to use to set up our search bar and bind the results from that search bar to our table view.
So let's go ahead and call phunk bind search bar search bar and we're going to go ahead and start by
just calling a search bar or a search field.
Yeah you know we should rename it search field because it's not really a bar.
OK so a search field is our textfield here.
As you remember from the simulator.
OK.
That's this here the search field so we can actually go in and access the R X property we can access
the text from that textfield and now upon this we can call all kinds of crazy functions right we can
link them together just like we've learned in the first sections of this course.
So we're going to actually start with one we've never talked about called or empty.
OK.
And what or empty does is it basically transforms a property of type nil like an empty string into a
string.
Basically it just sets it up as an empty string.
So if there's nothing it just converts it to an empty string which is pretty cool.
And as we call these functions I'm going to go ahead and put them beneath where they're supposed to
go.
And so let's say that we type in three letters to our textfield we're going to go ahead and map those.
Now so-called dot map.
And then using map we're going to go ahead and enter this little map closure here like so.
And remember when we use map we can access every element that we are using which in this case is every
element of our string.
And we can use a dollar sign zero to access those maps sort of like a for loop that loops through everything
with exception to this being we're typing in the text field here.
We're going to set it up so that if we type characters that are not you are all friendly we're going
to make them you are all friendly like if we were to search for something with a space if you know anything
about you are ell's a space is equal to percent sign to zero.
So what we're going to do is we're basically going to set it up so that any any text that comes in is
you are all compliant.
So we're going to convert everything to make it your L tech so that it doesn't cause any issues.
So go ahead and type dollar sign zero adding percent encoding.
That's what we need to do because we can add that percent in coding for a while with allowed characters
and we're going to allow the character set and inside character set we can access you RL queery allowed
and that's basically going to convert everything into a u r l query.
Now the interesting thing is is what if we don't type anything we shouldn't be converting like an empty
string into a dollar or a percent sign to zero.
Right.
It's not really a space it's just empty.
So if we don't have anything we're going to use the ternary operator to go ahead and just return an
empty string.
OK.
So now anything that we search we're going to go ahead and map to you our LFA it.
And now what we're going to do is we're going to take this and we're going to use flat map in order
to convert the search query into an observable of type repo array.
So go ahead call DOT flat map and.
Whoops sorry.
And the string here that's coming in.
What we're going to do is we're going to call that query.
OK.
Now this is the generic observable convertible type.
What we're going to actually do is we're going to return observable of type array of Repo.
Right because that's what we want we want our table view to update with this observable and we're going
to pass in our trending repo array.
That's what we have been doing.
So we should definitely continue to do that.
If you think about trending feed the sea we use the published subject of type rethrow and we use that
to pass in our trending repo array and that's how our table view can be updated in real time which is
really neat.
So we're using an observable here because we want it to be a little bit generic with how we're using
it.
So go ahead and you know put this on its own line.
And now inside flat map we have a query meaning the text that comes through when we actually use this
it's going to be returned as an observable.
That is of type array of repo.
So if the query is equal to an empty string.
Right because that can come in if it's empty.
What we're going to do is we're going to go ahead and return an observable and we're going to use the
specific type that we need array of repo and we're going to go ahead and type it just.
You should remember using this just allows us to basically create an observable with a single element
and that single element is going to be an empty array.
Right because if our search is nothing then we should have an empty array.
Very cool.
Otherwise meaning if there is a search query if we have typed something we should go ahead and basically
create a u r l.
Right.
We have our search you are l and we need to basically take our query and add it to our search you are.
So check it out.
Constance here and our search you are is this.
Now if you remember our query is going to go after the Q equals so we can do search you r l plus queery.
Right because our queries coming in through our flat map.
All right.
So go ahead and just type let you Arel equals search U R L plus queery And if you remember we created
another segment here to sort them by stars descending.
So we can go ahead and add the stars descending segment to the very end.
So go ahead and do search you r l plus queery plus plus stars descending segment.
And now we have a U R L that is comprised of all of our elements which is amazing.
So now instead of using Alamo fire you know what I think I'm actually gonna go ahead and just get rid
of Alamo fire for this view controller.
I want to show you how to do it with an S you are all session.
OK we do have access to Alamo fire but this isn't an Alamo fire course so I want to show you what is
possible thanks to you are in session.
So basically we're going to go ahead and create a web request using your session then we're going to
go through and parse through all the data we're going to go ahead and create repo's and then return
them as an observable of an array of repo.
So go ahead and just type return you Arel session.
OK.
And we're going to go ahead and access your all session.
Shared our X and this.
The reason we are able to return this session is because thanks to our X Ko-Ko we can access the reactive
part of your session.
OK so this gives us reactive properties and that basically allows us to return things as observables
not just as normal swithe types.
So you are all session shared are X and now we can call datt Jaison.
How cool is that.
And we can basically passen a u r l and it's going to create an observable full of Jason.
So what is r u r l u r l k we already created it.
That's super neat.
So what we can do is oh you know what sorry we need to basically cast this as a u r l.
So go ahead and put u r l dot hold up.
Let's see you are old.
Maybe it's you are ill with string.
There we go.
OK.
And the u r l is there.
OK because that is of type string.
So now we can do is we can take all of the sun data.
Oh sorry we've got to force unwrap it first.
There we go it's yelling at me.
So go ahead and call that map and we're going to use map actually to take the Jason that comes in.
We're going to cast it as an array of dictionaries like we have been.
We're going to actually go ahead and with a for loop we're going to cycle through.
We're going to create a repot that contains all the information that we need.
Okay.
And then we're going to go ahead and pen that back to our observable just like so.
So we now can go ahead and type results because you know your el session has results.
Type let results and that's going to be equal to dollar sign zero.
Right because that's the sun that comes in from map we're mapping it.
So we're going to take whatever comes in and we're going to go ahead and map it as any object.
Because at this point we're not sure what the Jaison is coming in as it could be anything since it's
coming in as any object we're going to go ahead and pull out the specific array of dictionaries by typing
let items equals results.
Object and you'll see that there is an option here object for key of type any.
And we're going to go ahead and pull out these specific key of type items.
And if you remember in our download service when we first download all of the repo's the initial array
is called items and you know what we could be using Alamo fire.
But the reason we're using you are el session is because we are able to access the X property and Alamo
fire in and of itself doesn't have reactive capabilities.
So here we go.
We now have access to our Jason array of dictionaries called items and in order to actually use this
we're going to go ahead and cast it as an array of dictionaries of type string and any just like so.
OK.
So that's great but we have a potential problem here.
What if we don't get any results back or if we search for something.
And there are no results.
We're going to use the ternary operator to just return an empty array like so.
OK.
So if there's nothing if there are no results we're going to go ahead and return an empty array.
That's just the way we can be safe.
So items is our Jason array of dictionaries for the results that we potentially will get.
So assuming we get a bunch of results go ahead and type for item in items meaning for a particular repository
we're going to go ahead and set up a custom repo that returns the data we need.
Now we're not going to use all of it of course because we don't have the contributors count.
We don't have an image et cetera et cetera.
So we're going to use guard let to ensure that we definitely do have the data we want.
So go ahead and type guard let And just like before we're going to go ahead and create a property for
each of the properties we want.
And then at the end we will call else return.
If we don't have what we want.
So guard let name.
It's going to be equal to item or remember item singular because each one is a dictionary.
And in that item we're going to go ahead and pull out the name and whips and cast it optionally as a
string.
Now we're going to go ahead and type let description equals item wups
description as string
then we're going to go ahead and type Let us language.
We do need that equals item
as string.
What else.
It's looks like we have indented improperly here we should not have.
All right cool.
So we have the language.
Next we're going to do.
Let forks count equals item and the key here is fork's underscore count.
We're going to cast that as string as well.
Then let repot u r l equals item and it's going to be HVM l underscore u r l as string K and we are
now at the end of what we need.
So we can go ahead and say else.
Whoops that should be a string else.
And think about this we're inside of a for loop.
So we want to break out of the for loop and then go to the next item.
So we're just going to call break.
All right.
That's great.
So now that we have gone through we've created this guard let for all of our properties to ensure that
we get them every time.
So now we can go ahead and create a repository and then we will return that to our observable.
So go ahead and type let.
Repo equals repo.
And let's go ahead and let's fill in everything we have.
So we have name we have a description we have a fork's count.
We have a language number of contributors we don't have what we do have a repo you l.
Now since we're not actually going to be using this we could have created it as an optional type and
returned nil and to be honest we probably should have done that.
But I'm just going to go ahead and return 0 then for the image we're going to go ahead and return you
I image named and the name is search icon large and we're going to force unwrap it.
OK.
So there's a repot But what are we going to do with that repo's the question.
What's the problem.
Oh I see forks count doesn't actually come in as a string.
It comes in as an integer.
And that will make that error go away like so.
Boom there we go.
So OK thinking about what we're doing here.
If the query is empty We're returning an observable of an empty array of repose.
Now what we're doing here is basically we're looping through all the repos for our search query and
we need to be returning them to some kind of array.
So up here we're going to go ahead and create that array like so.
So type.
Var Well var search repo's and that's going to be equal to an array of Repo.
OK so let's just go ahead and just instantiate it.
And when we create a repo after we loop through in our For loop we're going to go ahead and just call
Search repo's like so and append our repo.
OK so that is now appended.
But at the very end we need to go ahead and return search Tripos K to the observable because remember
we can pass in an empty array or we can return our observer and actually you know what we should return
on an observable of type array of repo's and are not repo's singular Ribault.
And go ahead and call just and the element here is going to be search repo's because that's our that's
our right.
That's what we should be returning.
So now we go look at this it says cannot convert expression of type observable repo to return type array
of repo.
So I guess it does want us to just return an array of repo's I guess because this r x property of u
r l session is already creating an observable.
So we just return we return the array and then the u r l Session returns the observable.
That makes sense.
OK so basically what we need to do now is we need to set this up to be observed so beneath you you'll
see if you can check with the brackets there flat map is appear at the top and at the end of flat map
we need to call observe on and it's asking for a schedular.
We basically need to just tell this that we want to observe this on the main schedular because we are
immediately affecting UI changes so go ahead and call main schedular instance.
OK so that's cool.
That's going to allow us to observe it on the main schedular.
OK so that's cool.
That's observing on the main schedular.
And now our search field is bound and it's ready to basically take in search results and it's going
to return observables of an array of repo which is really cool.
So the only thing we have to do next is to set up our table view.
OK.
So we're going to go ahead and bind our table view and this is the easy part guys we already did this
in trending feed Visi you'll remember this is all we had to do to bind our table view.
Super easy.
So basically all we have to do is just continue on in our function for bind search field and you know
what.
It's not very descriptive.
I'll just call this bind elements because we're binding the search field here to our table view.
And basically this this is going to end up returning at very very and it's returning an observable of
type array of repo.
So we should actually create a property for this.
We should say let maybe search results observable.
OK so it's going to be equal to search results observable and well I guess we should indent all of this
and make it go in really far like so because it's supposed to be directly beneath all of this but it
just starts to get really convoluted.
I'm going to move it back I don't like that.
So you get the idea.
It's supposed to be here.
And this now is equal to a property right and this property if we look into it it's an observable type
array of repo.
So let's go ahead and let's set up our table for you now to be bound to this.
So go ahead and call Search Result observable and now just like before in training feed the C we took
our data source which was of type published subject which is an observable and we bound it to the table
view.
So on this observable call bind 2 and we can call table view X and then we can call it Dot items and
we can call a cell identifier which we've already created.
The cell identifier is search cell K super easy.
Now what we have to do is we can call row repo and cell just like before.
So inside of this little function here we can call row Ribault of type repo and cell type search cell
k.
So we now have access to this.
But in order to show that this is a closure we need to include the in keyword so now that we have that
we can call cell which is of type search cell Dom configure cell passes the repo and the table view
is done.
Now we can actually access that but it's giving us a problem it says result of BIND is unused.
That's because we need to go ahead and add it to our dispose bag.
So add it to the Dispose bags.
We don't waste any memory.
Go ahead and return that so that it goes down below where it is supposed to be.
And guys we are super duper close.
I think we should go ahead and just give this a shot.
We should go see if we can actually search and present search results because basically what this is
going to do is it's going to take whatever chunk of text we type.
It's going to pass it in to the u r l that we create right here and then that your end is going to generate
all of the results.
So let's go ahead and build and run.
Let's go try this out and see how we did.
I know this is really intense reactive programming stuff we haven't done yet but the simple stuff is
sometimes the stuff that gets you.
We forgot to call bind elements.
Let's go ahead and do that.
And let's build and run.
And let's go check to see how we did
OK here we go it's running.
We load our initial stuff that's great but let's go to our search field.
Let's enter a search query and let's type our and we get results back.
Look at this.
Look at all those results.
Let's search for our X swift and look at that man.
We get all of our results back exactly as we wanted.
That's amazing.
All of our stuff.
But you know what I notice.
Look at this.
We are going to be getting a crash because every single time we type in a character we're going to be
getting an API call right.
Every single time that we type a letter we're trying to spam the API and that actually is causing a
crash in our application.
But if you remember we have a really helpful function called debauches.
So after the or empty call go ahead and type debauches set the do time interval to half of a second
and the scheduler is the main scheduler instance.
Now when we search it's going to wait half a second until we're done typing.
So go ahead and build and run and then we're going to go ahead and take a look to see if what we did
is going to help us to avoid crashes.
Here we go.
So let's go search our X Swift.
OK so there's that.
And let's go ahead and let's delete something fast and type a letter T.
Didn't make a search didn't make a search didn't make a surface to do really fast didn't make a search
and go back.
OK.
And it makes a search.
So this is going to help us avoid API spamming and causing unnecessary crashes in our application.
But guys this is amazing.
We have a hub search engine that we just built.
Look how cool this is.
OK so amazing.
In the next video we're going to set up the custom delegate for this table view because at the current
moment we're not using the table view delegate or data source so how can we make a call for a specific
cell.
How can we know what happens when we tap on a cell.
We're going to set a custom reactive delegate in the next video and we're going to basically set it
up so that we can use those extensions with an R X delegate.
Very very cool.
Let's move on to the next video and let's do it.
Amazing progress guys let's keep going.