We have been doing quite a bit of work in Interface Builder recently, and we are going to keep at it in this post as well. IB is an amazing tool that can make app creation a lot easier. In this post we are going to talk about IBActions, and how they are similar to IBOutlets, but very different at the same time.
Let's see if you remember what our last post was all about. We talked about IBOutlets, can you remember what they are? What they do? How to make them? How to hook them up?
We use IBOutlets to hook up graphical objects in IB to corresponding object declarations in code. So if you have an IBOutlet object in code, and you change some of it's properties, those changes will reflect in the object in your view. Pretty straight forward.
The concept of IBActions is very similar. Instead of hooking a graphical object up to an object reference in code, you are hooking up a graphical object to a method, or an action. Let's think about that for a second. Why would we want to hook up a Button to a method? Well, do we remember what methods do? Methods allow us to run specific pieces of code exactly when we mean/need to. So if we have a button on our view, and somebody touches the button, chances are we want something to happen. This is easily accomplished with the IBAction. We can hook up the IBAction to a graphical object in code (usually a button), and so every time that button is pressed, or that action is fired, the associated IBAction, or method is executed. Let's take a look at what this looks like in the header file:
As you can see the IBOutlet from the last post is still in there. IBActions are declared in the header file just beneath the @interface. You may notice that the declaration looks very similar to that of a method. This is because they are in fact very similar.
So the above code declares an IBAction for us, so what is left? We need to do something with it, right? Based on what we've talked about already, where would we do that? The .m file! Go ahead and put this in your implementation file:
As you may have noticed, the top line of our method, or our method signature, is the exact same as in the .h file. So something that is easy to do after you declare the IBAction in the header file is to copy that line and paste it right into the .m file. Then you put the brackets in and you're ready to fill out the implementation of the action.
So based on what we have learned about NSLog, what would you expect the result of this IBAction to be? We are printing a message to the console. How do you get to the console? Try Cmd-Shift-R.
So we have our IBAction declared in our .h file, and implemented in our .m file, are we done? What is missing? Well, we have an action that is ready to be used, but we haven't hooked it up to anything! The fact that we are using an IBAction, as opposed to just a regular method, means that the actual hooking up for the action will take place in Interface Builder.
In order to return to IB, go ahead and click on the ExampleViewController.xib (or whatever your file is called) file in Xcode. Similar to how we did it in the previous post, go ahead and right-click on the File's Owner button on the left, and notice what has changed. If you're building on the previous post's content, you should still see your IBOutlet hooked up, but at the bottom of the black popup we see a new area called Received Actions has shown up. Do you recognize anything in there? It's our IBAction!
By setting up the IBAction in the .h/.m file, we have the ability to hook up our action in IB. Similar to how we did it with the IBOutlet, go ahead and grab the open circle to the right and click-drag it to the button that we have on our view. You'll know you did it right when a black popup prompts you to select which type of touch event you want to respond to.
I haven't ever really found much use for all of these different options, but you are basically looking at all of the different ways that a touch can be recognized in proximity to a button. The one that we want to use (and that you'll want 99% of the time) is the third from the bottom: Touch Up Inside. This means we want to IBAction to fire if we touch inside the bounds of the button. Pretty straight forward.
With that, we're done! Go ahead and fire up your app and see what we have done. If you want to observe the effects of our IBAction, open up the console and you can see that for every time you press the button, a message is printed in the console.
This might seem like a simple concept, or result, but the concept behind it will be used very often. We just went through and hooked up a graphical object to our code, and are able to respond to events that happen.
Because just printing to the console is kind of boring, I want to spice it up. For our next post, we are going to review many of the different operations we can do within the scope of a method/action implementation.