[Seminar] [iOS: Writing Apps Like a Boss] [Tommy MacWilliam] [Harvard University] [This is CS50.] [CS50.TV] All right, everyone, welcome to iOS: Writing Apps like a Boss. This seminar is going to focus on writing apps for the iPhone and in turn writing apps for the iPad, and so we're basically going to walk through a couple different examples of how to make an app, a simple game like Tic Tac Toe, or if you're more interested in making an app like some kind of news reader or something that interacts with the Internet I will talk about that as well. Here's our brief agenda. IOS apps are written in a language called Objective-C, and so this is a little bit similar to C but not really at all, so we'll be talking a little bit about the language itself and then how to build iPhone apps using this app program called XCode, which if you haven't downloaded it yet feel free to start the download now. It's several gigabytes. It should be free on the App Store, so you'll need to have a Mac ideally running the latest version of OS X. If you're not, no problem. We have Macs in the science center available for your use with XCode installed, and so feel free to use those for development. If you want to make an app but don't have a Mac, don't worry. There's plenty of campus resources for that. And so then we're going to cover 2 larger examples of different apps you can make. Objective-C is technically what's called a super set of C. That means that any C code is also valid Objective-C code. That means that we kind of duct taped on some additional features to C. Some of these features include not having to ever write malloc again, thank God, no having to worry about those stupid pointers and freeing them and all that stuff you hated about C, and it's kind of gone in Objective-C. Now, Objective-C also has a much larger standard library, so there's a lot more functionality you get for free inside of Objective-C. Remember when we were writing PHP we noticed that we went from this smallest language to the giant library of all these crazy things you can do. The same thing happens in iOS. There's objects for things like the Buddhist calendar, and really anything you can possibly think of probably exists already in Objective-C's implementation. The objective part of Objective-C is referencing something called Object-Oriented Programming. This is kind of a new concept, but we've actually mostly learned a lot of these concepts already. The idea behind Object-Oriented Programming is that you're going to structure a lot of your code around these things called classes, and these classes are really glorified structs. Inside of a struct we basically said here is a thing, and this thing can have members. For example, a node in a linked list could have other things like a value, a pointer to the next node in the list, and together that pointer and that value composed this one instance of a struct. Classes are very similar except classes can also have functions inside of them. When we declared a struct, we could only say int n or node *next. Now with Objective-C we can actually put functions inside of those things. Another thing that classes can do is they can inherit data from other classes. For example, we'll be looking at a bunch of built-in Objective-C classes. One of them could be the class that represents the view for a screen, and so by saying I want to implement my own view we basically say someone over at Apple, probably really nice people, wrote this class for me, and it handles things like displaying buttons or rendering the screen, and we would be really pained to implement all that functionality ourselves, and so by simply inheriting data we can say everything that you did in that class I also want inside of my class, and then I'm going to do some other stuff, namely implement an app. That's what that word inheritance means. We'll see a more concrete example. And finally, the key with Object-Oriented Programming is that it leads to data encapsulation. In some of our problem sets we could have these big, global variables and globals everywhere, and that's how we'd keep track of state. With classes we can start encapsulating information inside of an object. If we have one screen on our app, we don't really need to have any data from another screen in our app inside of that, and so by encapsulating things within classes this actually leads to much better code design, and this is possible with some of the additional features of Objective-C. Forewarning, the syntax for Objective-C is bananas. It is like nothing we've seen before, so it is a little bit of a learning curve getting used to what the heck does this mean? But once you get past that initial learning curve it's really, really smooth to start writing apps. To declare a class, to say here is my class, it exists, and maybe here are some things that I'm going to define later, I'm going to say @interface. I'm going to say @interface. I'm going to give my class a name. And then later somewhere else I'm going to say @end, and everything in between the @interface and the @end is going to be my class. That is going to be what's inside of our .h files. Just like in C our .h files basically said here are some things that will exist. I'm not necessarily telling you what they do yet, but the compiler needs to know that they exist. Later inside of our .m files—because m for Objective-C is where we're actually going to define what these classes do. Much like our .c files, we provided an implementation for functions. Inside of our .m file we're going to say here is what all of the functions inside of my class—what they all do. And finally, inside of a struct we could say inside of those curly braces int n or node *next, and in Objective-C we're going to use the keyword @property, and this is what's going to define the properties, or the non-functions that are a part of my classes. Calling functions in Objective-C is also bananas. When we declared functions in C we said something like int foo and open paren and then gave it a list of arguments. This is what declaring methods or functions looks like in Objective-C. If I want to declare a function or a method where I'm saying method is really just a function that's a member of a class, so kind of interchangeable, but not really, so inside of my method I want to create a new method. It's going to return nothing, so it's going to be of type void. This is the return type of my function. Now we have parens here because—I don't know. Next is going to be the name of my function, and then finally we have a semicolon just like we had in C. What's new here is this guy here. This hyphen is actually necessary, and what this says is that this method here must be called on an instance of a class. After we declared our structs we probably said something like struct node n, and that actually created or instantiated one of those structs so that I could actually start working with what's inside of it, so this dash means that we have to instantiate the class just like we instantiated that struct before we can call this method on it. If I want to start adding arguments to my methods it gets even more bananas. Here's my method name. Then I'm going to have a colon, and after this colon it says here comes some arguments. This method takes one argument. The type of its argument is an int, and the name of that argument or the variable that I'm going to start using inside of the method is called i. Again, this is method. It takes one argument. If you want to start adding more arguments it gets more bananas in that we have this colon that says here comes my list of arguments. This first argument is an integer. Now, this second argument is interesting. The variable that I'm going to be using inside of my function is called f, so inside of my function I could say f + = 1 or something. This thing here is basically a key for that argument or parameter. Just like we had key value pairs and something like JSON or associative arrays Objective-C made the decision to say, okay, just so that it's really clear when you call a method what all these parameters are I'm actually going to name them all. When you call a method, you'll actually say andFloat, and then you'll pass it in. Interestingly, this one is not named, but all of the other parameters are, so if we had a 3rd argument I could say andFloat and another float and so on. When I call these methods it is of course bananas, so if I have an object, and I defined a method called foo, and I want to call it, rather than saying foo open/close parens I'm going to open a bracket. Here's the name of my method. I'm going to close the bracket, and this is the object I'm calling it on. Remember, all of these methods exist within classes because classes can have methods defined inside of them. Here I've arbitrarily created an object of some class, and this is the syntax for doing that. There are 2 steps to creating an object. The first step is to say I want to allocate space. This is the equivalent of a malloc. We don't have to say malloc anymore. We dropped the m, made it alloc, and replaced the .c with .m. After we alloc something we then need to initialize it. Basically when you create objects you might want to have some logic that executes when they're created, so you can pass in some default values or something like that, and so this init method is what actually creates the object. We first allocate space, just like we did in C, and then we initialize it, which may or may not do a whole lot. Then we're returning this thing into an object o. There's a star here because this is technically a pointer, but don't worry, pointers aren't that big a deal in Objective-C anymore. Now we've instantiated this class called NSObject, and this is just a random class that Apple has. We've instantiated this, and now I have an instance of this class in this object o, so that means that if I defined these methods I could call them like this. Similarly, if I wanted to call a method with one argument, so this is the bar method, that takes one argument, and here is the baz: qux method, so this takes 2 arguments. This is calling one function on this object o. Make sense? The syntax should make sense, but you kind of get used to it. Okay, let's talk about a few things that are built into Objective-C that weren't necessarily built into C. In C we kind of had to deal with strings as these stupid character arrays, and it got really annoying. Objective-C has those all built in for us, and it's built in using this class called NSString. When I want to create an NSString we have more arcane syntax. Rather than saying "cs50" we say @"cs50" and this is just the syntax for declaring strings in Objective-C. This is extremely easy to forget, so don't. Now, once I have this, this is a string, but notice it's really just an object. I said NSString, which means I instantiated the class called NSString, which someone else wrote for me, and they were very nice about it, and so now I can start calling methods on it. If I call the method length on this object s it's going to return to me the length of the string. This is just like strlen in C. This would return 4. Similarly, another method I might want to care about is this characterAtIndex. This is a method that says on this string s I want you to get the zeroth character, and so this would return to me the character c, and there's a whole bunch more of these methods that you can Google really easily. Apple's documentation is great, and we'll take a look at that in a bit. Those are strings. We also have variable size arrays built in. Remember in C when we declared an array we had to say you have 5 elements, end of story. When we got to JavaScript and PHP we could start doing things like adding elements or moving elements. We can do the same in Objective-C. Rather than create an array in the normal C way we have again another class called NSMutableArray. There's also NSArray, and this is going to basically encapsulate some array. This says the first thing I want to do is I want to allocate space for a new array, and after I allocate it I then need to initialize it. Again, just calling these 2 methods. Now this means that inside of this object a I have an empty array sitting there. If I want to add something to this array, I can call the addObject method. I want to add an object to the array a, and I want to add the string CS50. If I wanted to conversely remove that I can say I want to remove the object at the first place on the array or object a. Make sense? Okay, you kind of get used to this square bracket thing. By the way, inside of a lot of Apple's libraries you'll see this NS. The NS actually stands for next step, which was one of Steve Jobs first companies, and that's where he really started writing a lot of the code as kind of the basis for Mac OS X and all of the other stuff, and so this NS is kind of this nice legacy shout out to one of the earlier companies back when Apple was first starting out. It's everywhere. Let's take a look at a more holistic Objective-C example. Here I am inside of XCode. To get here, I first downloaded XCode from the App Store, opened it up, and then I went up here to file, over here to new, and then project. After I do that I have all these options of what I want to create, and so we'll take a look at these options later, but just for this example, because we're not actually going to have an app yet, I came down here, and I said Command Line Tool, and this is an app that I could run at the command line just like we've been running from C. That's how I created this project, and so now I'm here, so let's first look at this file, and this should look pretty familiar. I have an int name. There's my friend argc, my other buddy argv. And so we can see that this is the entry point for my first Objective-C application. Here we can ignore this for now. This is basically some memory management stuff that you won't really ever have to worry about. Let's look at this first block here. This first line, if I say Student* alice = [[Student alloc] init] what's that doing? This first student here, this is probably a class. This isn't a class that Apple wrote, but it's a class that I wrote. The first thing I want to do is I want to allocate space for a new student, and then I want to initialize it, so this gives me back this new student object, and I'm storing this in a variable called Alice. Where did that class come from? Well, over here on the left side these are all of the different files inside of my project. We can see here I have a Student.h and a Student.m. The .h file, remember, is where I declare all of the things that will exist within the class. Let's take a look at that. All right, here we have this @interface, and this says that here comes the declarations of everything that will exist within my class. Then I have a colon. Then I have this NSObject thing. This colon signifies that inheritance bit we were discussing a little bit earlier. This says everything an NSObject can do where NSObject is this class written by somebody else, everything this NSObject can do I want to be able to do that. By saying :NSObject that means that I basically inherited all of the functionality of another class. That really gave me a whole bunch of different methods and properties that I can use. Down here I'm creating 2 properties. That means my student, if this were a struct, these would be the 2 things inside of my struct, so every student has a name that is a string, and a student also has a grade, which is an int. Finally, down here I'm going to create a method for my student. I called my method, initWithName, and it takes one argument, and that argument is a string, and I called it name. Now let's look at how we actually implemented this class. Here, now I'm inside of my .m file, m for implementation, I guess. I have my implementation, my end, and here is where I'm actually defining what initWithName does. I have initWithName, the name of my parameter, and then this is where I'm actually creating a student, and so this is a little bit cryptic, but this is kind of boilerplate that you want to include in your constructors. This initialization function here, initWithName, is a type of constructor. You're basically constructing a new student object and maybe sending some data inside of it. The first thing I want to do is I want to call init on this super thing. Remember that when I said back here in the .h file that everything an NSObject has a student also has. That means when I create a student what I also need to do is make sure that the NSObject that I'm inheriting all of that data from is also initialized properly. What I need to say is this super is actually going to refer to the parent class that I'm inheriting from, so I want to make sure I initialize everything that I'm depending on before I start trying to use it. Then if that initialized correctly this is just like saying if malloc did not return null then I can start setting some properties. In JavaScript and PHP we had this keyword called this, and this referred to the current instance of a class. In Objective-C we call this self. When I say self.name, that means that the object I just created when I said student alloc init, that's going to give me back an object. That means I want to set the name of that object to whatever I just passed in. Just like in C, we access members with this dot, so self.name says the name of the student object is now going to be whatever you just passed in. And so finally, I can return it so I actually get something back. Questions? Okay, so this self = super init, if you don't totally understand the inheritance stuff don't worry. Just know that if you ever want to make your own init method just do that, and you'll be good to go. Yeah.>>[Student] What does if self mean? This means when we malloc something we always checked if it was equal to null, and if it was null, then we exited. This is the same thing, because if this returns null, then we're probably going to seg fault if we start trying to manipulate it. That's our student class. That means we can initialize our students in one of two ways. If I say student alloc init I'm not using that method that I just wrote, and instead I can simply say alice.name, and now I'm going to set that property name. Similarly, if I want to use that initWithName method I can simply say alloc, and then rather than saying init I'm going to call that method that I just created, and I'm going to pass in Bob. At this point, this object Bob has a name equal to Bob. Okay, down here I'm using that NSMutableArray that we looked at earlier. I'm allocating space.Then I'm initializing a new array. I'm going to add 2 things to it. This array now holds student objects. Notice that nowhere did I have to say this is an array of students. I said it's an array, period. Then I can put whatever inside of it that I want. Here I have 2 objects. Finally, I have another object here, this TF. Over here in TF.h basically the same thing. I'm inheriting from NSObject, and by the way, when you create classes this is all done for you, this kind of interface boilerplate. It has a property of students. I have a couple methods here that don't really do a whole lot, and so that means after I create this TF object I can call this method grade on it like this. Any questions on Objective-C syntax before we start moving into some more interesting apps development stuff? Okay, so let's actually make an iPhone app. The core classes that you'll be using inside of your iPhone app are called view controllers, and a view controller basically represents a single screen inside of your app, so if I'm on the music app, for example, one view controller could represent the view in which I view all the songs on my iPhone. Another view controller could be when I click a song and start playing it or as I'm drilling down into artists. Each of those different screens could be represented as a different view controller, and a view controller is really just a class that says how this screen works. Things inside of a view controller, we're going to have properties, so things like a button is going to be a property of our view controller. We're also going to have methods, and these are basically event handlers. This method says when you press this button I want to do something, and finally, again, we're going to be using this self keyword to access the current instance. To build interfaces in iOS is actually really, really easy. They have this nice drag and drop interface called Interface Builder, and the 2 core concepts that wire up your Objective-C to Interface Builder are IBOutlet and IBAction. An IBOutlet simply says that if you declare a property that's a button, and you want to hook it up to something in your actual UI, you're going to say it's an outlet. Similarly, if you want to represent an event handler then you're going to say it's an action. To actually wire up this graphical representation and your code it's really, really simple. If you want to attach an IBOutlet, all you have to do is you control click, and we'll see an example of this really quick. You control click where it says View Controller. You're going to drag into the interface, or conversely, if you want to hook up an event handler you're going to drag from the interface in the other direction. Let's take a look at a really simple iOS example. Let's create a new project. I'm going to come up here to Application, and I'm going to click Single View Application. I'm going to click next. I'll give my project a name. I'll call it Hello. Interestingly, Apple assumes you're creating a product so that you can sell it and they can make money. Down here I'm going to say that this is an iPhone app. You can create an iPad app, or if you want to create one of those apps that supports both devices you can do that too. These are what you want your checkmarks to look like. You want to use storyboards, which we'll see later, and you definitely want to use automatic reference counting, which is a nice feature that prevents you from having to say malloc and free. Unless you want to call malloc and free, I would leave this checked. I'll click next, and finally, this is going to ask me where I want to save it. I'll hit create, and here we go. I created a new project. Over here on the left are all the files that are inside of my project, and notice that I got a whole bunch, and I didn't even do anything. IOS is great. For example, here this ViewController.h, this is going to represent my first view controller, so the first screen inside of my app. Now we know what this is saying. We're saying I'm calling this class ViewController, and a ViewController does everything that a UIViewController does, and this, again, is some class that Apple wrote that does a lot of handy stuff for us like display the screen. Here is where I can actually start defining what my view controller does, and it turns out that I really don't need any of this. This is boilerplate code that Apple gives me for free. I did need that first line, or I don't have a class, so we can get rid of that and get rid of this. Okay, so this is my empty screen. Now let's click on this MainStoryboard.storyboard, and this is where it starts to get interesting. This represents the first screen on my app. If I want to add a button, in HTML I had to create a button tag. In Android you have to create a button tag, but in iOS if I just come down here to the bottom right and if I click on this 3rd one here where it says Objects, and I can scroll down, or I can start searching for button. And look, a button, so if I actually drag and drop this right there, I've just added a button to this screen on my app. If I want to change the text, I can double click it, say something enticing like "Press Me." Okay, now if I run this app, so we compile it, so to run it I click the play button in the top left, and there's my app. I didn't do anything, and I got a sweet looking iPhone app. If I want to stop it, you can click the stop button because it's more fun. Let's say that I actually want something to happen when I press this button. To do that what I need to do is I need to create a new event handler or an action. That means that I need to create some method that I want to be called when I press the button, so let's create a new method. I'm inside of ViewController.h. I need to say that a method exists. I need a hyphen first because I'm going to be calling this on the view controller. I need to give this a type. The type of this is going to be that IBAction thing that we saw earlier. This is an event handler, so it's going to return an IBAction, and this is a hint to XCode to say that this is something I want to wire something to. I can give it a name, like buttonPressed, semicolon. Now I've declared a new method inside of my class. I've said this method has to exist. Now let's come into ViewController.m, and let's say what this method can do. If I start typing, for example, (void)buttonPressed notice XCode is really nice and autocompletes for me. That's really wonderful. Notice here that inside of the .m file I can also say void, and this is because that IBAction isn't actually a type. It's actually hashtag defined somewhere to be a void, and again, this is just a hint to XCode that says I want this to be an event handler, and we'll see why in just a second. When this button is pressed I'm going to do something annoying like display a popup. To do that I can create a new instance of this class called UIAlertView, and this is a class that Apple wrote that's going to display annoying popups. We'll call this popup alert, and I have 2 steps, remember, to creating this object. The first thing I need to do is allocate space. I want a UIAlertView. I want to allocate space. That's my first method. My next method is I want to initialize it, and so I have this big, long method called initWithTitle. That's basically going to control what this popup says. The title of my popup can be hello. The message of this popup can be "This is iOS." Delegate thing, I don't know what that is. Let's say it's nothing. Now the button that's going to appear can say something like "It sure is," and I don't really want any other buttons, so let's delete that and close the bracket. Okay, I created an extra one. There we go. This is how I can create a new popup. If I want to actually show the popup I want to call the show method. To do that I can say alert and show, and again, autocomplete was super nice. If I forgot what that was, if I just typed in s, I can scroll through here to figure out what it was, and it filters nicely. Now I created this new popup. We'll come back to what delegate means later, and now I want to say I want this method to be fired when I press the button, so I'm going to come back to my storyboard, and I want to now attach this IBAction. The first thing you want to do is click the button. When I press this button I want something to happen. I'm not going to hold down control. I'm going to click and drag from the button to over here where it says View Controller. We can see that it nicely lights up. If I let go with my mouse I now have this popup over here where I have some options. One of these is the events that I can register. These are all of those methods I declared in my h file as IBActions. This is how XCode knows what should appear in this little list, so that's just a hint. If I click on button pressed, I've now registered the event handler. In JavaScript we had to say I have some code that registered the event handler. In Objective-C it was really that easy. If I run this again now when I press the button my event handler is going to fire, and I'm going to get this popup. Super, super simple there. If you ever want to see all of the events that happen to be registered on a component if I click on this button and I come over here to the right side first you can see over here I can do things like the type of the button, so if you want one of those I's or the add contact button or whatever. If I want to see all of the events that are on this button if I come all the way over here to the right side we can see here at the events I have all of these different events. I can press the button, when I let go of the button, when I double tap or whatever, and the one I just registered is this event called Touch Up Inside, and this says that as soon as my finger comes off the button that event is going to fire, and that's exactly what just happened. This is kind of the default button pressed event. Any questions so far? Okay, that's how we can start to wire up things in our code into things inside of our interface. Remember the first thing we had to do was to find the code, and then we wired up the interface to the code, and there's our first app. Okay, that was really cool, and we created this button. What if we don't want to have to create a bunch of properties representing these buttons? For example, in Tic Tac Toe I have 9 buttons, and it'd be super, super annoying to have to drag and drop 9 times or if I had to make Tic Tac Toe with 81 instead of 9 and I had to drag and drop 81 times, and that's lame. What we can do instead is much like an HTML when we had things like IDs and names and we can search for things by their ID, there's a similar notion in iOS called tags. A tag is simply a unique numerical identifier for a component. If I say this has a tag of 0, for example, if I create a button and give it a tag of 0, and we'll see how to do that in just a second, if I want to get that button I can simply say I want to call the viewWithTag method on the object over here, the self.view, which represents the current screen, for example. If I call that viewWithTag method, I'm going to pull back the button with tag 0. Let's take a look at this by building Tic Tac Toe. First, this is my storyboard. I've created these 10 UI buttons. Notice they're all the same size. If I click one of these and I come back over here on this right side you'll see I adjusted the font right here, so I made the font a little bit bigger, but what I also did was I set this tag. I said that this has a tag of 1, and that's the top left. Now, if I click another button, like this second one here, now you'll see that my tag is 2. Each of these buttons just has a unique tag, and so this is later how I'm going to start interacting with my app. This is all inside of one view controller, but here is what we have. We have 3 properties here. The first one and last one are going to represent the state of my board. Basically this first one is an array representing where the Xs and Os are. This other one here tells us whose turn it is. You'll notice that I also have these things here. Before when we declared properties we gave them a name and a type. We can also give them some additional information here. This first says nonatomic, and what this says is basically only one thing will ever be trying to access this variable at a time. You could do more complex applications that are multi-threaded, and so back in Scratch we had different threads, and different sprites could be doing different things at the same time. If that's not the case, which it is not in anything that we'll be looking at, if we say nonatomic it's actually going to make things a little bit faster. We also have this thing called assign, strong, or weak. This assign just says that this is a standard type. This is not an object or a pointer because this is just a bool, so bool is built into Objective-C. This says don't try to do anything fancy with pointers here. It's a regular old scaler. Strong and weak, this weak says that actually I want this to be pointing to something in the view controller. I'm not going to actually allocate or init this myself. The interface builder, when I run the app, is going to handle all that initialization. If I say weak, that says someone else is going to be creating this. If I say strong, this says that I'm going to be the one that's creating this board object, and so here I have some more methods here, for example, an action for when the new game button is pressed, an action for when any of the other buttons are pressed, and et cetera. We won't get into too much of the logic of Tic Tac Toe, although it's very exciting, but let's take a look at some of the things that we can do inside of iOS. This new game method is going to be fired whenever I press the new game button. To hook that up I simply come over to my storyboard. I clicked on new game. If I come over here to the right I can see that Touch Up Inside is wired to the newGame method. That's why this is going to get fired. The newGame method is going to do some set up. It's going to say I want you to clear the state of the board. This is a nice method on mutable arrays. This is going to say it's now X's turn, and now I'm going to take advantage of this viewWithTag thing. I know that my buttons have the tags 1-9, and that's something I arbitrarily picked. If I want to set the text of each button to be empty because I just started a new game and I don't want any Xs or Os to be left over I can do this. I can say I want the view with the tag, 1, 2, 3, 4 et cetera. This will pull a different button each time. Here I'm going to cast it to UIButton. Just like we could cast ints to floats and vice versa this says that I want to cast this to a UIButton. That means the type of this will be a UIButton* because of pointers, but don't worry, they're not scary anymore. Once I have this button I'm going to call a method on it. This method is called setTitle forState, and so this says I want to set the text of the button to be the empty string, and I want it to be the empty string when it's not pressed. If I'm using this method, I can change the text of the button as soon as someone hits it, but we want to say when the button is just sitting there I want the text to be blank. Finally, we're going to initialize my board, and I'm going to say that everything is currently at 0, so this board members immutable is a mutable array, which means I can call the addObject method and just a 0 inside of it. That's what happens when I create a new game. Let's take a look at another one. This method here is the IBAction that's going to be pressed every time one of those squares is pressed. Now we have some Tic Tac Toe logic here. We figure out whose turn it is, and based on that we either set an X or an O, but we notice that we're reusing this same event handler for every single one of those buttons. That means that I don't have a method for the top left button, a different method for the bottom right button, although I could have done that. That wouldn't really be good design. What I'm doing here is I'm actually going to determine what the tag of the button that was pressed is. You notice that this play method takes one argument. It's called sender, and what sender is is sender is going to represent exactly what was taken action upon. If I press a button, this sender is going to be that UIButton that I actually pressed, so that means that that UIButton has a tag because I created a tag. If I want to get at the tag I can simply say I want the tag of the sender, and again, I've just casted it to a UIButton. I happen to know that the sender will be a UIButton. It doesn't always have to be a UIButton. I could, for example, register the same event handler for one for a button, one for a slider. In this case, I know they're all buttons, so I'm going to say I want this to be a button, and then I can get the tag, and from the tag I now know where I am inside of the board. Then I can simply set either the X or the O, can flip the turn, check who has won, et cetera. Any questions on this so far? Okay, all the code we posted online—we don't want to get into too much of the Tic Tac Toe logic, but now you can see that really all we're doing is we're looping over this array, so we have a couple of for loops here, and we're just comparing to see do we have a match in all the rows, a match in a column or anything like that. To actually run this app, if I tap on one of these buttons that play method was fired, so that means I just set the button to be an X, so now this button will be an O, and so on, and so that's how we're starting to interact with this single page app. We'll post the code, so feel free to peruse that, but let's now talk about some apps that are more than just one page. As exciting as Tic Tac Toe was, a lot of apps inside of iOS are kind of these drill down things with multiple screens. The first concept that we'll need to talk about are protocols, and a protocol is simply a set of methods that you can promise to define. If I create this new protocol with 2 methods, this first one, if the return type is void, I called it foo. It takes no arguments. I have another method. It returns an int. I called it bar, and it takes one argument. All this protocol is that's called SomeProtocol up here, this is a set of things that someone can implement. I haven't inside of this protocol said what foo does. Instead, I'm just saying you could define foo if you want to. If I'm creating a view controller or creating a class I can inside of that class promise to implement some of these methods, so for example, if say this now says I'm making a promise to you that inside of this view controller class I will have definitions for both foo and bar. Why is that useful? A lot of components inside of iOS take advantage of this design pattern called delegation, and what delegation says is that, for example, if I have a text box and there are some events that could be registered inside of my text box, rather than creating separate events what I can do is I can say the delegate of this text box will be some object. When I say that this is a delegate now that means that whenever some event would have been fired in the text box rather than having to register it or anything like that it's just going to call a method on the delegate. For example, inside of my text box I have a method for when I press that done button in the bottom right, and so rather than registering event handler what I can say is text box, here is an object that I want you to call a method on every time someone presses the done button, and that means that that object has to implement some protocol that says I promise to define that done button action, because if it doesn't define that method and you press done, then it's going to be confusing. Let's take a look at an example. Here I simply have one text box, and one of the properties of this text box over here on this right side is the delegate. This is a property of the class. What I did here is I control clicked, and I dragged from this spot over here to the view controller, and that says now the delegate of this text box is going to be the view controller. That means that when some actions happen, rather than registering separate event handlers I want you to send them to the delegate. Now let's take a look at my view controller. Inside of the .h file I've made a promise. I've promised to implement some methods inside of this protocol called UITextFieldDelegate, and again, this is just some list of some things that I can choose to implement. If I come here in my .m file, I have implemented one such method. I've called it textFieldShouldReturn because that's what it was called inside of the protocol. And now whenever I press the done button inside of that text field this is what's going to get called, so I did not register an event handler. I connected the delegate, and whenever this event is fired this is the method that will get called, so if I come over here to my storyboard and run it— while that's loading we can see what this does. On my screen I have 2 things. I have this text field, and I have this label. I'm simply saying I want the text of this label to be equal to whatever the user typed in inside of the text field. This next line here is simply a method that I'm calling on the text field that says I want you to hide the keyboard. This is just the arbitrary method that Apple chose. Again, before I did anything I had to wire everything up, so I first came over here. From the view controller I drag over to the text box. I let go, and I can see here that I can make this the text field property since over here in the view controller I've defined a property that is an IBOutlet of a text field. This says that I can wire this property up to a text field in my UI. Now when I click this I can start typing. Now if I click the done button this is going to fire an event that I can now respond to. No event handlers. That's how I just responded to that done button. Make sense? This isn't a design pattern that—you might not ever find yourself creating your own protocol, but just know that some different iOS components register events in different ways. Buttons, for example, use those IBActions. Text fields, on the other hand, are going to use delegates. We can see and you can look all of that up inside of the documentation. By the way, there's actually a ton of UI stuff built into iOS for you, so for example, the way I made that say done at the bottom right is I selected this text field. I came over here. I scrolled down a bit to return key, and I can actually make this a whole bunch of things, like if I want that to say emergency call instead I can do that, which is totally random, and I don't know why there's a built-in emergency call button, but there, it says emergency call in really small letters. There you go. Definitely explore all of these different options in iOS. Any questions on delegates? Again, just an interesting design pattern that you should be aware of. Okay, let's next take a look at table views. A table view is basically that list of items that is all over the place in iOS. When you're flipping through all of your contacts, you're looking at the setting page, and that kind of list of things is called a table view. Implementing a table view in iOS is pretty simple. Instead of making a class that descends from that UIViewController like we've done before we simply need to say rather than everything a UIViewController does I want to do, I say everything a UITableViewController does I want to do, so that simply adds some additional things that are totally done for us. We need to do very little to basically fill in the blanks inside of the table. In order to display a table I need to answer some questions. The first question I need to answer is how many sections are in the table? When you're flipping through your contacts app you'll notice that it's kind of organized by the As, then you have the Bs, and you have that little sub header. Each of those is called a section. You may or may not need these. The first thing you need to do is implement a method called tableView:numberOfSectionsInTableView. That simply returns how many sections you have, so this could say return one if you have one big table view. The next question that iOS needs to know is how many rows do you have? For example, you're flipping through a table view. You have a fixed number of songs you're looking at or a fixed number of contacts. If you're me, of course, not that many, and so that's how iOS knows how many cells to display. Again, this could say something like return 3. My table view has 3 rows. Finally, iOS needs to know what each cell looks like, so what it's actually going to do is call this method down here, this tableView:cellForRowAtIndexPath. It's going to call this method on every single cell inside of your table. How does it know how many times to call it? Well, you told it inside of number of rows in section. We're going to call this on each of our cells, and inside of this is where you can actually do things like set the text or tell you what that little blue button on the right side does. The pattern for getting these cells, we're going to use this method called dequeueReusableCellWithIdentifier. Objective-C is actually very well known for the ridiculous length of their method names, and this is really a nice case in point example. What this method does is this just says I want you to give me a cell. Just an iOS thing. If you have something like 100,000 songs on your iPod what iOS doesn't want to do is allocate 100,000 cells, because if you're at the top of your list, do you really need to allocate memory for the cell that's 99,000 rows down? No, because as you're scrolling you can kind of allocate as you go along. This is done for you. You don't have to worry about all that stupid performance stuff. All you say is you call this method dequeueReusableCellWithIdentifier, and this says, okay, if you need to I'm going to create a new cell for you. But if you're at the bottom of the table and you've already allocated some cells at the top of the table that you're really not going to need anytime soon I'm going to give you one of those back instead of allocating a new one, and so this is a nice performance concern. You do not have to allocate the cells yourself. That's going to give you back a cell. It's going to return to you a cell object. Once you have the cell object you can do stuff to it. You can set the text of the cell with this property called text label. You can add that arrow on the right or some other random stuff with this other property called accessoryType, and so on and so on. Let's take a look at actually implementing a table view now. When I created this project rather than saying single view application I actually came over here to master-detail application, and so basically this corresponds to the mail app on the iPad with the table view on the left and then the contents on the right. On the iPod or iPhone this is going to correspond to a single table view. That's where I got my starter code. Let's first take a look at the storyboard. All of this was done for me, basically created. This navigation bar showed me what an example cell could look like, and I can double click this, change the title. Any other UI concerns I can handle there. The header file looks really simple. Rather than saying this is UIViewController we're now saying this is a TableViewController, so we know that we want to call all those table methods. Next I want to create a property that's going to represent the things inside of my table. This table is going to arbitrarily display a list of fruit, and so I need to create some array in which I can insert fruit. Inside of my implementation file the first thing I want to do is I want to make sure I initialize this array. I said alloc init, created my fruit array, and I'm adding 4 things to it, one of which is much more controversial than the other 3. And now I have an array of size 4. We're shaking it up in CS50. I now have an array of size 4. Now I'm going to start answering these questions, and actually, when I created this app all of this was already done for me. I didn't have to type out the number of sections in table view. It was already there, and I'm filling in the blanks. How many sections do I have? One. All done. How many rows do I have? Well, I have one row for every fruit, so this count is a property of any array that says how big is it? That's how many rows I have. Finally, I need to say what does each cell look like? I'm going to say dequeueReusableCellWithIdentifier. Again, this was already written for me. I didn't have to do this myself, and I want to get back this cell at this location. Remember that we're calling this same method on every single cell, and this argument here, this indexPath argument, says what row I'm in. If I say indexPath.row down here this will be 0, then it will be 1, then it will be 2, and this is so I know what cell I'm currently displaying. I want to set the text of the cell using this textLabel property to go inside my fruit array and get the object corresponding to each row. If this is a string, I'm now setting the text property to a string. I can do one other thing. I can also register an event handler on each of the cells, so when I tap each of these cells this didSelectRowAtIndexPath, this is going to be called for me, so simply by defining this I can now handle what happens when you tap a cell, and again, we're passing in which cell was tapped so that we can reuse this same event handler for all of our cells. Again, this is something iOS is doing for me. Let's display another annoying popup that simply says you picked something where that something is going to be the row object. When I run this, I'm going to have this nice table view with one row for each of these fruit, and if I tap one it tells me what happened. Make sense? Let's build a little bit more complex of an app, as much as clicking you picked tomato is. The nice part about the storyboarding is it's not only going to help us design screens individually, it's also going to help us tie together our entire app, so the final app we'll be building is this nice sports news reader, and so it's going to have multiple screens, and so I can actually represent each of these multiple screens on the storyboard, and I can zoom out and see my app from a high level. In order to create a new element inside of my storyboard it's really simple inside of Interface Builder. If I want to add another screen to this, for example, I can first zoom out with the pinch zoom that Apple loves so much, and down here before I search for a button and I drag and drop a button if I want to create a new screen I can actually just drag and drop an entire view controller, so if I pick this, pull it over here, hey, there's another screen, and so now using this same storyboard file I can have all of the screens inside of my app, and I can zoom out and see how they interact. These won't interact yet. The way in which these 2 screens interact is you define relationships. You can basically say this screen, when you press this button, I want you to slide over to this new screen. That means there's this kind of relationship between the first screen and the second screen. You'll have basically an arrow from that button to the second screen saying that when you press this button that's where I want to go. Just like we control clicked and dragged to define those outlets we're going to do the same thing to define these segues. We'll see an example for that, and before we actually transition from one screen to another iOS is nice enough to call this method called prepareForSegue, and this is where we can start sending data from one app to another. In the example we're about to look at it will basically allow us to filter baseball teams by leagues and divisions. When I select a league, for example, I want to transition to my next screen where I can display all of the divisions in that league or all the different teams. I need to send to that screen what teams you should display. To do that I'm going to take advantage of this method here. Finally, just a random point on iOS. If you want to store data there's this thing called core data, which is actually kind of complicated to work with. You can also use SQL to store data, which, again, is nice but kind of on the more complicated side to work with, but iOS also supports these really cool things called property lists, and a property list is just a file that represents key value pairs. You define a list of keys, and you say this key is going to be an array. This key is going to be a string, and basically anything you can do in JSON you can do inside of a property list, and so this really nicely allows us to work with some data. For example, I have this Teams.plist that I created. I created a new plist file, and I can drill down. This is a dictionary, this is a dictionary, these are strings, and so this is a nice graphical representation of a JSON document or just a set of key value pairs, and so this is the data that I'll be working with inside of my app. Let's first come over here. We have a lot more files now. But let's first come over here to the storyboard. The storyboard here—if I can zoom out— we can now see that this is the flow of my app. I'm first going to start on this screen. I'm going to drill down to this screen, and I'm going to drill down to this screen, and we can see here that if I kind of move one of these around we have these arrows going from here to here, and the way I define that arrow was if I zoom in a little bit, and if I come over to this view controller, and here's a cell, and I want to say that when you tap a cell I want you to slide over to another screen. I can simply hold down control, scroll over a little bit, hold down control, drag this cell over and let go. And over here we say what's the transition that you want to use? Do you want to use that slide thing that's called push? Do you want to slide up from the bottom? That's called modal. And once I click one of these, it's going to draw this arrow for me, and that means that I've actually handled what happens when I press this button graphically. I didn't write any code to actually slide from one screen to the next one. I defined this visually inside of Interface Builder. If I click on this arrow, we can see that I gave this thing a name. I called it showDivisions, and this is so that I can know what transition is about to occur, and we'll see why in just a sec. That's how I've wired up the different screens in my app. If this were a button, for example, rather than a table view, I could control click on the button, drag over to the next screen, and that's how I can do navigation that way. Really quickly, if we come into the MasterViewController, again, we're simply going to define a list of things that will be displayed in the table view. Here I'm saying I want you to take that plist file, and I want you to load it up into a dictionary, and once you have that dictionary, I'm going to answer those same questions again. Here is the number of sections. One, there is one row for every league, and the text of each cell should be either the first one, the first league, the second league, and so on. Finally, I'm going to use this method that we just saw called prepareForSegue, and this is the method that's going to be fired when I click on one of those rows and therefore activating that transition that I set up with the arrows. This is saying that I can have multiple relationships from one screen to another. If I have 2 buttons and each button takes you to a different screen I'm going to have 2 segues, 1 for each button. But this prepareForSegue is, again, going to be reused for each of the different relationships, so that means that I need a way of identifying if you press the first button or you press the second button. Remember when I gave that segue a name, this showDivisions, that's how I now know that this is the segue that was activated. All I want to do is I want to say I want to figure out what I just hit, and so to get that, I can say I want the indexPath for the selected row, remember the indexPath just says where I just clicked, and then I want to say I want to figure out where I'm going. This destinationViewController, that's a property of the segue. That's the screen I'm going to, so I know that the screen I'm going to is called DivisionsViewController because I created that class, and so now if I say d.divisions I'm now setting a property of the view controller I'm about to go to. This is how I'm sending data from one screen to another screen. Just looking at this DivisionsViewController you can see here that in the .h file there is that property divisions, and that's what I'm basically populating, so that's how I know that I'm displaying the divisions corresponding to the league that I clicked, and again, the actual table view looks pretty much the same, just answering those 3 simple questions as well as identifying what happens when you move to the next screen. Just a couple of other things here. You notice at the top here that rather than saying #include I'm now saying #import. This is just an Objective-C thing. The import is basically a nicer version of include, and for example, we need to know what this class is, so I can't just say DivisionsViewController. If we didn't hashtag standardio.c inside of our .c file the compiler had no idea what printf was. Similarly, if I don't import the DivisionsViewController the compiler really has no idea what a DivisionsViewController is. Just make sure that inside of your different .m files you make sure to import the corresponding .h files so that the compiler knows what's going on. Finally, what Apple ultimately does is display some data using a web view, and so a web view is an object in which you can embed a little web browser inside of your app. All you need to do is supply a URL to your web browser, so I want to go to mlb.mlb.com, and this is how I can access the home page for each team, and so by passing in this URL the web view can display this for me, and I can browse around, and simulator is in use by that one. Now this came from my plist. If I click this this also came from my plist, and this sliding was handled by defining those segues. I click this and one more, and now here is my UIWebView, so just like that here's the website for the URL that I just embedded, and I didn't have to handle anything crazy. This is how to display a web page. Things like this back button here are also given to me totally for free because I've defined these relationships using segues. Any questions? Yeah. [Student] So when you use alloc, you never have to free anything? Exactly, when you call alloc and init you do not have to free it. IOS is going to handle all of that for you. It's wonderful, and you're not breaking any rules. Yeah. [Student] If you were to include more teams that could fit on the screen, would it automatically have a scroll option, or is that something you need to add? Exactly, if I had more teams, for example, it would automatically handle the scrolling for me, and all the performance concerns with the huge table are also handled totally for me. Other questions? All of this code is going to be posted. We kind of glossed over a little bit of the more minor details, but things like setting some properties to the web view are just things that you can get by browsing Apple's documentation, which is really, really nicely laid out. They have a lot of sample apps and example usages of different APIs, so definitely peruse those if you can. Just some helpful links you might want to take a look at. These are some handy documentation guides. The URLs are massive, so they're shortened. This first one is the entire library of documentation. There's little search bars, so if you start typing button it will start giving you all the information about all the things you can do with a button. I've also included the Table View Programming Guide. It handles table views in much more detail, how to do things like dynamically add cells or edit cells or remove them. There's lots of sample apps from Apple that will show you how to do that, and finally, this last one is the Human Interface Guidelines, and this is basically some discussion of UI components, things like don't make a button that's 4 pixels by 4 pixels. That's a bad idea, and other things that Apple wants you to do to encourage good design. Any last questions before we finish up? All right, definitely feel free to—we're going to have special labels on Discuss. We'll have an iOS one, so definitely feel free to utilize that. If you want to work with your classmates on projects or help figure out some random iOS stuff feel free to email me, and definitely peruse all the code online because just in the interest of time we kind of glossed over the more finer grained details of things. But if not, then good luck on your iOS projects, and I hope we have a big influx of apps in the App Store. [CS50.TV]