Hey guys this is Caleb with Debb slopes and in this video we're going to set up the sending of messages
in group feed visi.
We're going to upload them to firebase in our group.
We're also going to go ahead and we're going to set up a function in our data service to download all
of our feed messages for the desired group that we want and we're also going to do a really cool table
view scroll animation so that when a message is sent it'll scroll the table view all the way to the
bottom.
And so that we can see the most current message is very cool.
So let's go ahead and let's pull open our X code project and we're actually going to start by setting
up how the send button works we're going to set it up so that when we type a message and press send.
It's going to upload a post to our desired group.
Now I don't know if you remember this.
It was a while ago but we've already set up a function in here called upload post.
And when we were doing that we added with group key.
It's optional and we didn't use it but we need to basically set up what happens when we want to upload
a post to a certain group.
And so that's really easy.
Thankfully all we have to do is basically go into our groups reference.
We have to find the specific group thanks to our group key.
Then what we're going to do is we're going to basically go into the messages array then we're going
to go into the messages child which may or may not be created.
Thankfully firebase will create it for us and then we're going to go ahead and go into that child and
update the child values to include all the message content that we need.
So let's set that up really fast.
Like I said we're going to go into ref groups.
We're going to go ahead and go into the child for the group key which actually we don't need to do it
like that we can just say group key.
All right very cool.
We need to force on Rapido because it is optional coming in.
So now that we are in the specific group let's just take a look at firebase so we can remember what
we're doing here.
OK.
So cool.
In each group you'll notice there are three components but I want to add in a messages array that's
going to hold all of the messages that we need.
And so what we're going to do is we basically just passed in the key.
So now we're in the proper group so we're going to go ahead and we're going to pass a child in that
we have not yet created.
But when we send a message it will automatically create it.
It's going to be called messages.
And then what we're going to do is for each message we're going to create a child by Auto-ID it's going
to just be a random thing because each message doesn't necessarily need to be linked by its I.D. to
a specific user because inside that child we're going to pass in the sender's I.D..
So inside this new child inside of messages we're going to go ahead and update child values with a dictionary.
This is where we will pass it content.
OK.
Just like a feed just like a feed cell if you remember the feed cell has content and a Sender ID and
the content will come from the message passed in with the string appear message.
Then we're going to have another one called Sender ID.
OK.
And that will come in from the ID we pass in.
OK remember that.
Very cool.
So that's super simple.
It's basically the same thing as down here.
But this will create a messages folder inside.
Any group will assign each message a random ID and then inside that will have content message and the
sender ID from the ID.
So that's good to go.
Now let's go ahead and let's right get all messages for a desired group.
That is the function we want and we're going to put it right beneath it all feed messages because it's
kind of a similar function.
So let's go ahead and put it right in the middle here.
And like I said the name is phunk get all messages for desired group.
Now I'm just going to use.
I won't use an internal parameter for this.
I'm just going to pass it a group.
Then we need a handler that's going to return all the messages.
OK.
So go ahead and type handler.
It's going to be escaping like always.
And then we're going to have to go in and put some parentheses here some curly brackets and for what
actually escapes the closure we're going to just call it messages array.
And it's going to be an array of type message which we already created.
Just like up here.
Very cool very simple.
So what we need to do is we basically need to go through and find the right group.
We need to find the messages and then we need to cycle through and create all the messages that we need
and append them back up to the group.
Basically like we did here we observed the feed we created a snapshot we cycled through all of them
created message objects appended them and then return them.
So we're going to do the same thing but let's start with an array that we're going to actually append
all of our messages to.
And let's call it var group message array and it's going to be an array of message.
Let's instantiate it.
And now let's go ahead and let's observe the desired groups messages child so type ref groups dot child.
Now of course the key is going to be the group or sorry the desired group.
We're going to force on rapid there.
Now we're going to go ahead and oh you know what.
Sorry it's not optional.
So we don't need to we don't need to unwrap it that way.
So we are in the proper group that we've selected then we need to go into the messages child so choose
child by path string and type messages.
Then inside of that we want to observe the whole thing.
So we're going to type observe single event of type value.
We're going to observe all the values and this is only going to happen once.
But we're going to call an observer from the actual view controller so that when a change happens it'll
cycle through and update all the changes.
And this will this will prevent basically any issues of this being called multiple times and loading
the data multiple times.
I ran into an issue with that but I found that this is a great solution.
So for the closure go ahead and call data snapshot group message snapshot because it's coming specifically
from the group.
And now we're going to use guard like we have to create a constant holding that snapshot guard let a
group message snapshot equals group message snapshot children all objects.
And we're going to cast it as a an array of data snapshot.
If we can't do that or else return and now we have a group message snapshot so now let's go ahead and
cycle through that four group met groups with two O's group message in group message snapshot.
We're going to go ahead and basically do what we did up here.
We're going to get the content and the sender ID then we're going to go ahead and pull that together
into a message object.
And we're going to append that to our message.
So let content equals group message child snapshot for path content.
And we want the value and we want to cast it as a string so that it can be added as text data.
Then we want the sender ID.
So go ahead and type let sender ID equals group message child snapshot.
The path of course is sender ID.
We want the value of that and we want to cast that as a strength.
OK.
Just like we did with the content.
Now we're going to create a message object by typing let message equals message and let's instantiate
that bad boy and we're going to give him some content.
There we go and we're going to pass it a Sender ID as well.
Excellent.
Next after we have created our message object we're going to append that to our group message array.
And you know what just to be specific I'm going to call this group message.
So now that we want to append that we're going to type group message array append and you'll see it
requires a message which we have in group message perfect case so once that's all done after the for
loop is finished we're going to call our handler which asks us to return an array of message which we
have in group message array.
This function is going to be handy for returning all the messages for the specific group that we want.
Let's go ahead and let's set this up in group feed Visi now.
So when we go into view we'll appear we load all of the titles stuff we load all of the emails.
That's great but now we're going to go ahead and observe our groups reference and we're going to call
get all messages for desired group.
So let's go ahead and call data service instance ref groups and we want to observe all changes.
If anything changes we want to update all the messages.
So go ahead and call observe and we're going to type value because we want to observe all values changing.
Now the snapshot for this one we don't care about because we're not actually using it we're just using
this to observe our groups reference.
But what we are going to do is call data service instance to get all messages for a desired group.
Well what group are we going to pass in the group that we downloaded when we initialized the view controller
so called self group because we are now inside of a closure so we have to call self.
And that's the group that we want and this will give us all the messages back that we need.
So let's call this returned group messages.
I'm just going to copy that.
That's a long name.
And now that we have this returned we should set an array locally in this view controller that will
hold all those messages.
So let's go ahead and do that.
Let's create var group messages and that's going to be of course an array of message and we're going
to instantiate it.
Really cool.
Next we're going to go ahead and let's think we need to set self dot group messages to be equal to returned
group messages whichever messages got returned back.
That's what we want to do.
All right.
And now now that we have those group messages returned we can call self table view reload data and all
of the messages will flood in and show up where they're supposed to be.
But we have a problem folks we have not yet set up our table view in this view controller.
Let's do that now.
I'm going to tab down here so you can see plenty of things.
And we're going to do this with an extension by typing extension group feed Visi and we're going to
conform to you table view.
Delegate and you table your data source like we have like 100 times in this course.
And we need number of sections in table view number of rows in Section and cell for road index path.
That's great.
Let's return one section.
Let's go ahead and return the group messages array count because we need to return how many messages
we have that's just makes sense.
And now what we're going to do is we're going to set up a cell and we're going to go ahead and initialize
it with everything that we need.
So go ahead and type guard let cell like we have equals table view dot dequeue.
So delegate dequeue reusable cell with identifier for index path.
And of course we have group feed cell.
We've already set up that name in the main storyboard.
And we're just going to give it the index path.
OK.
Now we need to cast this as a group feed cell and if that doesn't work else we're going to return a
table view cell just instantiate it like so.
But assuming this works which it will we're going to go ahead and configure our cell.
So go ahead and type cell doc configure cell and like always it needs a profile image and email and
content.
So let's give it that from our group message array we can pull out the message for the index and get
all the data we need by typing let.
Message equals group messages and we can just pull the index path dot row to get the specific message
all the way down.
We've done this throughout the whole course.
So let's go ahead and let's pull out message dot sender ID.
Oh that's a problem.
We'll fix that in a second.
So we don't have an e-mail yet but we can get it.
So for the content though we can definitely get message content for the e-mail.
We're going to have to use our user name function.
So go ahead and call data service instance don't get e-mail.
Let's see to get username for your cause remember we called it username.
We really should have called e-mail.
But what we can do is we can pass the message sender ID and the handler of course is an e-mail so we
can move our configuration of the cell into this function and for the e-mail we can just pass an e-mail
that we get back from our user named function.
The profile limits though is another story and we can actually just go ahead and call you image named
and it's just default profile image.
We're not going to actually download or upload images for this section of the course but that is something
that you could do to extend this app.
Hint hint now that it's configured we're going to go ahead and return the cell.
And now we should be good to go to get all feed messages.
The only issue we haven't set it up to send yet we can't do anything if we push that send button.
So let's go ahead and let's send a message.
We need to make sure though that we actually have typed something so let's make sure that the message
textfield is not nil or empty.
So go ahead and type if message textfield text is not equal to nothing.
It's not empty.
We're going to go ahead and disable the textfield.
We're going to disable the button as soon as we press it so that we can't press it multiple times and
send multiple messages.
It's just kind of a nice way to just verify that we don't send accidental input so call message.
Textfield dot is enabled What is enabled is false and send button dot is enabled is also going to be
false.
Then after that we're going to call data service instance and from this point it's just like uploading
a post to the feed.
We're going to take message textfield that text unwrap it.
That's the message we're going to send the I.D..
We're going to send is off from firebase Auth.
we forgot to import firebase.
Let's go to that import firebase sneaky thing.
And now for the off Id We can call off off.
Current User ID and it's going to yell at us in just a second but this time instead of sending it to
the feed we're going to pass in a group key which we can get from group Dom key.
We need to force unwrap it of course because it is optional.
And you know what it's yelling at us that we need to force unwrap the off as well.
That's fine.
Now oh interesting so I guess oh no no sorry.
Because I pulled it.
Optionally here that's fine.
We have a value and send complete is going to be a boolean that comes back.
Let's just say status and we're going to say well no maybe complete that makes a little more sense if
complete meaning if the send is complete we're going to re-enable message textfield that isn't enabled
equals true and send button did it again send button is enabled is also true.
Very very cool.
And when we send it we also want to blank out the message textfield so that it's empty again because
we don't want to send the same message twice.
So go ahead and type message textfield dot text is empty.
Very cool.
And of course it's yelling at us we're in a closure.
So we need to do self dot all these things now now whoops we deleted the whole thing let's try that
again.
Self-taught send button is enabled.
Let's go try it out.
This should work to send a message and to download all of them at the same exact time.
Let's give it a shot simulator is opening up.
It is building and running.
Here we go let's try it.
Click on groups click on nerd herd.
We have our e-mails.
Let's send a message.
Hey guys.
And you know what.
Let's watch firebase just for fun.
Here's our group and here we go.
Send
and nothing happens.
Interesting messages shows up here.
So it looks like we pressed send and nothing happened.
Well we said if complete it should re-enable everything and it should show in the table view but weird.
Yeah it appears it's complete it's an firebase.
Let's go look at that upload post function and let's see oh we never send We never used our händler
to say that we were done.
That's totally why it's not completing.
So let's call our handler here send complete and let's pass it.
True.
There we go.
That should be the problem we were just not telling it that the message was done.
So it had no idea whether or not it should know that it's done or not so let's let's try this out.
Let's go into groups let's open it up and we're still not getting any messages we'll have to investigate
that in a second.
But let's try to send a message Lou when I send it it looks like it sends everything goes away.
But our table view is definitely not doing anything.
Oh we didn't set up the table if you delegate or datasource simple stuff folks to this table view.
Delegate equals self table view.
Datasource equals self.
And let's build and run it.
That should actually solve the problem.
It's sometimes the simplest things that you just gloss over things I've done like a million times anyway.
So let's open it up.
There's our messages.
That's amazing.
Let's send it.
Batman rules.
And when I when I send it let's see what happens.
There it is.
Boom.
The message appears exactly as we hoped.
That is so so cool.
Amazing it popped up in real time just like you would expect.
Now the last thing we need to do is we need to set up a scroll animation for whenever we reload data
and get some new messages because we should have it animate to show the most recent message every time.
And to do that we first need to make sure we have messages because if there is nothing in the table
view this is going to cause a crash.
So if self doc group messages that count is greater than zero.
What we're going to do is we're going to call a self table view scroll to row an index path at your
table view scroll position and animated.
Well of course we want it to be animated and the position we're going to have it scroll to none.
OK and you'll see why in a second you can have it scroll to the middle bottom or top.
But sometimes there can be issues.
So none basically just tells it to scroll all the way to the index path that we set.
Now the thing is the index path is an interesting thing because we cannot tell it to scroll to the bottom
but we can tell it to go to group messages don't count.
So if we give it an index path and we call Dom in it to get the row and section what we can do is we
can basically say the section is zero of course because we only have one section and we're using that
we're using zero indexing here.
Now for the the row we want to scroll to the very bottom row and in order to get to that we could just
call self group messages don't count.
So let's say we had 30 messages I could scroll to the 30th row.
Right.
If we had 31 suddenly it would scroll to the 31st row.
But the issue is that the count shows the true value so if there are 30 messages it would come back
as 30.
But the array only goes up to 29 on the index because raise use zero indexing.
So let's go ahead and do self-talk.
Group messages don't count minus 1.
And believe it or not guys this will make a really cool animation that will animate to the very bottom
of our table view whenever we send a message.
So let's go ahead and build and run.
Let's go check this out and let's see how we did and we'll call this video.
Good.
OK.
Go to groups go to your group let's send some messages.
Hi yo yo.
And this one should animate nicely.
Nice.
See that it animates nicely but problem.
We're covering the table view.
We can see that it's animating but we need to fix that constraint.
So let's go into the storyboard here.
Let's go ahead and fix that really quickly and then we'll call this video quits.
All right.
So the table view the bottom constraint here goes to the very bottom of the view and that views just
happens to be on top of the table view.
Let's get rid of our bottom constraint and we're going to go ahead and it 8 to the bottom.
Well not eight but zero.
So that it matches exactly.
Up next to it.
Press Enter to set that constraint and let's build and run one more time.
That should solve our issue.
Guys this app is coming together it's looking amazing.
Great great job so far.
And guys we've done a lot of work to make this awesome.
So let's go ahead and head in there is our most recent message.
Let's send a new one Harvey stinks and send and it animates up just like we were hoping.
Now the cool thing is when you enter into this let's say people have sent new messages since you last
went and watch this.
When you go in that animates you see that maybe any to send a few more maybe send a few more here kind
of spamming my channel here.
OK let's go back and watch this.
Do you see that it animates when it pops up it's really really cool.
And I will be able to see it better later when we animate this in from the left.
But guys amazing work.
We now are getting group messages now to prove it.
It's not coming into this one faded boom.
Different messages for different groups.
Super super cool.
Amazing work.
Let's head over to the next video where we're going to go ahead and we're going to set up a view controller
extension that's going to animate this view controller to the left instead of popping up from the bottom.
And then we're done.
This app is finished.
Amazing work.
And let's head over to that next video now.