All right. 1
So now that we've seen the awesomeness of dark mode as well as vector image assets, it's time to move 2
on to the next thing which is learning how to use the UITextField. 3
Let's take a closer look at our text field in the Interface Builder. 4
Notice how we've got a text field right here which you can find from the object library. And it's right 5
here. 6
The text field is going to allow the user to use the keyboard on the iPhone and type in an input. 7
By default Apple's UITextField already knows how to handle light and dark modes, so that the color 8
of the tags depending on which mode we're in will be different. 9
So it will be white in dark mode and it will black in light mode, and the background color also adjusts depending 10
on the interface style. 11
Now, we can also set the type of keyboard that we want by changing these text input traits. 12
So for example, we could say that the capitalization for our inputs should be for each word because our 13
users are going to be typing in the names of cities. 14
So for example, this means that if they start typing the word "London," then it will automatically capitalize 15
the "L" here. And we've also got other things, such as the type of keyboard, so you can change the keyboard 16
that pops up to a number pad or one that is for e-mail addresses or Twitter. And we can also change what's 17
in the return key. 18
So the Default just says return, and you should be familiar with that 19
if you use the iPhone keyboard often. But I'm going to change it to Go because it seems to make more 20
sense when we are searching for the weather in a city. 21
And finally, I want to show you that you can also change the text to be Secure Text Entry. 22
So what this means is that when you have some text that is for a password field, you don't actually see 23
the actual text, so that somebody who's looking over your user's shoulders, won't be able to know what 24
their password is. 25
All right. 26
So now that we've seen this text field, let's go ahead and set it up. 27
So I've left all of this for you to do, so you can see how to set up a UItTextField from scratch. 28
Now, let's go ahead and control-click to create a new IBOutlet which I'm going to call the searchTextField, 29
and then I'm going to add a IBAction from this search button to say searchPressed, and then change 30
the data type to a UIButton. 31
And now I can tap into this IPBAction and see what the user's typed in the search field. 32
So the idea here is that the user would tap on this field, type in the name of the city, and then press the 33
search button at which point, we'll be able to see what they typed. 34
So as you might guess, the text field has some pretty common properties like the one that we saw earlier 35
when we were setting it in the Main.storyboard. 36
So if you select the text field, you can see it's got a text property like a label, but this corresponds 37
to the text that the user has typed inside here. 38
So we can get a hold of it by tapping into the searchTextField.text property which, again, corresponds 39
to the text displayed by the text field. 40
Now, that's different from the text that you see here in sort of a light color. 41
That is the placeholder text. 42
And this is kind of meant to be like the reminder for the user. 43
This is what you should type into this text field like it might say "Password" if it was in the password 44
field, or it might say "Enter a city name" if it's in this particular field. But it's kind of up to you. 45
But I think search seems to make sense for me. 46
This is where you're going to search for a city name. 47
And now we can go ahead and try to print what's inside our searchField.text. 48
So because the text property is a optional string because it doesn't have to be set, 49
it could also just be an empty string, 50
and, in fact, it tells you that the string is empty by default. 51
So we can go ahead and unwrap that if we want to print it without that little yellow warning because 52
we know that it's an optional, 53
and we know that we're going to type something into it when we print it to see its value. 54
So let's go ahead and run the app and see what we get. So when our app runs and you click in the search 55
field, it should bring up the soft keyboard, so the keyboard that's attached to the iPhone. If it doesn't 56
bring it up, then you can go into the Hardware menu for the simulator, and go to Keyboard and Toggle Software 57
Keyboard, or just use the shortcut of command K. 58
And that should hide or bring back the soft keyboard. 59
`Now when I start typing in here, you'll notice that we've currently got our Secure Text Entry selected, 60
and we've also managed to change the return key from the default which says return to go. 61
So I'm gonna go ahead and uncheck that Secure Text Entry. So I can see my words being capitalized even 62
without me hitting shift. Now that we've seen all keyboard in action, let's go ahead and click on the 63
search button, and you should be able to see the words that you've typed in their printed down here. 64
That is because we're tapping into these searchTextField IBOutlet and then getting its text property 65
printed. 66
But you'll notice that when I type a word in here, let's say, "London," and click on the go button, 67
nothing actually happens, even though you would expect that it would have the same behavior as our search 68
button. 69
So how do we tap into that go button? 70
Well, it's a little bit different from what you might expect. 71
We can't simply just create an IBOutlet to the keyboard and get a hold of when the keyboard go button 72
gets pressed. 73
Instead, we have to use something called a UITextFieldDelegate. So the first thing we need to do is 74
we need to add a comma after the UIViewController and type UITextFieldDelegate. 75
And this will allow our class, our weather view controller, to manage the editing and validation of text 76
in a text field. 77
So let's hit enter to add that. The next step is inside our viewDidLoad. 78
I'm going to delete the comment there, but I'm going to tap into that searchTextField and tap into 79
the delegate property to set it as this current class which is, of course, accessed using that "self" 80
keyword. Here what this line of code is saying is the text field should report back to our view controller. 81
For example, our text field will handle the task of our user entering text. When the user interacts with 82
our text field, 83
say, your user type something, then or text field will notify our view controller on what's happening. 84
The text field will say something like, 85
"Hey, view controller, 86
the user just started typing," or the text field will say something like, "Oye, view controller, 87
the user just stopped typing," 88
or it might even say something like, "Yo, view controller, the user just try to tap elsewhere, should I 89
let them deselect me?" 90
The idea here is that the text field can communicate what's going on. And the way we ensure that the view 91
controllers notified by the text field is by setting the view controller as the delegate. 92
Remember that "self" refers to the current view controller. 93
So what this allows us to do these two steps is we can now create a method called 94
textFieldShouldReturn. And this will ask the delegate which is this current class 95
if the text field should process the pressing of the return button. 96
In other words, the text field will say, "Hey, view controller, the user pressed the return key in the keyboard." 97
What should we do? 98
This is going to be the exact time point when the return button gets pressed and I get to write some 99
code to be triggered at this point. But once I'm done writing my code, I also have to return a true or 100
false that tells the text field whether if it should actually process that return. 101
In my case, what I'm gonna do is I'm just going to use this as if I have an IBAction to that return 102
button. And I'm going to print my searchTextField.text and I'm gonna force unwrap it. And finally, 103
we have to return true because this is a function that expects a boolean as an output, so that our text 104
field will be allowed to actually return. 105
So now if we hit run and we type a word into our text field and then go ahead and click on the return 106
button, 107
so this has been renamed go, but this is always known as the return button of the keyboard, then it will 108
trigger this function textFieldShouldReturn and we get the text inside our search field printed down 109
here, and we allow this return process to go through with our return true. So now we can get hold of what 110
the users typed into the text field from two places, either if they've typed in something and then press 111
the search button, or if they've typed something and then press the go button. 112
I know that a lot of people, at least me included, when I'm typing inside the keyboard, it's much quicker 113
for my thumb to reach the go button, 114
and I expect it to basically hit enter, kind of like the return key on a keyboard. 115
So both of these buttons now trigger the same thing which is for me to be able to get hold of what's 116
inside the searchTextField. But there is just one problem at the moment, I can't seem to get rid of 117
this keyboard no matter where I click, or if I click on the search or the go, it doesn't dismiss itself 118
like it should do. 119
It should kind of disappear because I'm saying I'm done with it now. 120
So how can we fix this? 121
Well, we can tell our IBAction searchPressed that in addition to printing the searchFieldText, it 122
should also make our search field and editing. 123
So, if we tap into this method code endEditing and set it to true, then it will tell the search field 124
that we're done with editing and you can dismiss the keyboard. 125
So let's put that in both places, the text field should return as well as the searchPressed. 126
So now when we run our app and I go ahead and type something into my text field and I press the search 127
button, then it dismisses my keyboard. 128
Similarly, if I press the go button, it also dismisses my keyboard. 129
So perfect. Now, what if we wanted to be able to clear what's in the text field to set it back to its 130
original state, 131
Once we click on the go button or the search button because at the moment, it's kind of leaving it in 132
there, even though we said that we're done with editing of the text field and we can dismiss the keyboard. 133
It's kind of weird to leave the text in there. 134
So how can we tap into this moment when the text field has ended editing? 135
Well, there's a delegate method for that. 136
Remember, the delegate is the one who is notified. By being the delegate of the text field, our view controller 137
can be notified when the text field ends editing. Similar to how we got hold of textFieldShouldReturn, 138
we can get hold of a method called textFieldDidEndEditing. 139
This is the equivalent of our text field saying, "Hey, view controller, the user stopped editing." And inside 140
this bracket, the code will be triggered as soon as any of the text fields on the screen are done with 141
editing. 142
So inside here, we can set the searchTextFields.text property to equal a empty string. 143
And when we run this code, you can see that as soon as I'm done with my typing and I press go, it clears 144
my text field so that I can type a new search term the next time, and it works both from my search button 145
as well as from my go button. 146
A nice thing about setting the textField.text property to an empty string using 147
textFieldDidEndEditing is that we avoid a bit of repetition. 148
Otherwise, we would have to do this twice. First, on line 26 after the search button is pressed, and then 149
,again, on line 31 after the return key is pressed. 150
Now, there's one final delegate method that's quite useful and it's called the 151
textFieldShouldEndEditing. 152
So if we type in the textFieldShouldEndEditing, 153
you can see that, again, it expects a boolean as the output. 154
Notice how all the methods that have the word "should" in the name are asking for permission. 155
This is the text field saying, "Excuse me, view controller, the user just tapped elsewhere. 156
What should I do sir?" 157
Should I allow them to stop editing? 158
Here our view controller gets to decide what happens when the user tries to deselect the text field. 159
But wait, why might you want to prevent your user to stop editing a text field? 160
Why trap them in editing mode? 161
Well, the textFieldShouldEndEditing method is actually really useful for doing some validation on 162
what the user typed. 163
So for example, we might want to check to see if the textField.text property is not equal to an 164
empty string because the user should really type something in there. 165
If we're gonna use that text to check for the weather, then we're kind of assuming that they've type 166
something, rather than it being an empty string, right? 167
So in this case, well, then we're going to allow our text field to return. So we're gonna say, 168
"true," it should end editing. But if it's actually equal to an empty string, then we're going to remind 169
or alert the user that they have to write something. And to do that, one of the easiest ways is tapping 170
into the placeholder property. 171
So remember that inside our Main.storyboard, we set our placeholder property to say, "Search," which 172
is what shows up in sort of a light gray color. 173
But in this case, we're going to change the placeholder to something to alert them that they should 174
type something here. 175
And then after that, we're going to return false. 176
We're not going to let the text field and editing yet. We're going to keep the keyboard where it is and 177
we're not going to trigger this method. And you can see that when I click in the text field and I try 178
to click return or click the search button and I haven't typed anything, then it's reminding me to type 179
something in here before it will dismiss the keyboard, end editing, and reset the text field. 180
Now, one thing that I want you to notice here is that notice how in these methods, I've been using that 181
IBOutlet we have created, the search text field which, of course, is a reference to that text field we 182
have in our screen. But down here in this new method, I've actually just referred to a textField. 183
So where does that come from? 184
Well, remember that we are not the ones triggering or calling any of these functions, right? 185
Nowhere in our code do we call text field should return or textFieldShouldEndEditing because they are 186
triggered by the text field. So the text field class is the one that's responsible for calling these 187
methods. And when it calls textFieldShouldEndEditing, when it detects the user dismissing the keyboard, 188
well, then in that moment, it's gonna pass in a reference to the textField that triggered this method. 189
So you could, for example, have a multiple text fields, similar to how in our IBAction, we can get hold of 190
the sender which was the UIButton that actually triggered this IBAction by detecting a touch event. 191
We can have multiple text fields or triggering the same methods. So if we had multiple buttons linked 192
to the same IBAction, then any of those buttons could be the sender. 193
It just depends on who detected the event. 194
And if we have a bountiful text fields, all with their delegates set as this current class, then any of 195
those text fields could be the trigger for these delegate methods, but they will pass their identity 196
in through this text field parameter. So if we don't care about which text field was triggered, then we 197
can simply just use this parameter and apply our validation to any text field in our current view controller 198
using this code. 199
So now that we've implemented our text field, the final thing that we want is no matter if they pressed 200
on the search button or if they pressed on the return or go button, we should be able to get hold of 201
what it is that they wrote which is the textField. text property. And I want to be able to use that 202
which, hopefully, contains the city name to check for the weather in that city. 203
The perfect place to do that is in our textFieldDidEndEditing method. 204
And just before I reset my search text field to empty text, I want to be able to go ahead and use the 205
searchTextField.text. 206
So whatever the user typed in here, "to get the weather for that city," and then and only then do I've reset 207
my searchTextField.text to an empty string. So that functionality would be the next step of building 208
out our weather app. But let's pause for a moment because we've introduced a pretty big topic in this 209
lesson and that's this idea of delegates and protocols. 210
So notice how this UITextField delegate is not a class, it's not a struct, but it's something called 211
a protocol. 212
And to understand what protocols are and why they're so useful, head over to the next lesson where we're 213
going to do a Swift Deep Dive on protocols and extensions. 214
So for all of that and more, I'll see you there.