[ Silence ] >> David J. Malan: All right. We are back. So Tminus one lectures to go. Tonight we finish our look at iOS and some of the features that we've hinted at thus far. And that might empower you to do some pretty cool things with your third and final project. In fact, looking ahead to exactly that, on Wednesday August 7th in lieu of lecture, we'll have an App Party of sorts where [inaudible] will convene across the hall where labs usually are held. We'll bring in some snacks and food and whatnot. And you'll bring your laptops and or iOS devices and the goal would be to spend an hour or so exhibiting each other's work and chatting and sort of did he briefing how the semester went. And showing off what your, hopefully, quite proud of. Whether that's your final project or either of the prior two. And leading up to that, next Monday, will be a couple of guest lectures. So I and all the TF's will be here. But we'd thought we'd invite a couple of friends. One is a fellow named Dan Armadorez, who used to could teach this class and taught in android aspect of it. What we thought was we'd give everybody some exposure to what android programming is like  what's similar, what's different  so that you can scratch that surface to see if that's a direction that's a direction you'd might like to go in next. And also we'll have a friend of ours from Microsoft Bob Familiar joins us to talk about windows mobile programming. Taking a look at how you might do it with C sharp, which is Microsoft's language for desktop and mobile programming as well as how you might also do it using HTML 5's. So that'll be our final glance for the semester. And we'll also tie up loose ends with iOS and give you a sense of where you can go from here around what you might want to keep in mind. So that once the training wheels are off, you can actually create some cool things on your own if indeed of interest. So with that said, how would we go about making something like this? So we saw our first application last week involving Rob last week. And what were the features we implemented to top Rob's three photos last time? Yes? Gesture. So we had a couple of gestures. We were able to swipe from left to right to move Rob from one side to the other. Or right to left in order to pan through his three Facebook photos. Thank you for sending him those Facebook friend request so quickly incidental ly. And we also had one other feature that we implemented atop Rob's face. Which was what? Alert, okay. But we've seen alerts before. How did we trigger that alert last time? Yes, so touching down or a long press. Or if you hold for a good second or two, that is the separate event that's fired that we call encode. And we said, "Hey, stop that," or something similar. So we had two such gestures. But we really didn't do a couple of the more familiar mechanisms whereby I might, for instance, want to just move something around. Now this is a little underwhelming on a back drop. But because this is rectangular, you can imagine having images or shapes of some sort where it makes sense to actually move these things around. And in fact, where it will end tonight is actually looking at how to do this programmatically. How do you create two dimensional graphics that move in response to user's action or to just move around on the screen on their own. So this is a translation of sorts. Moving up down or left or right. But you can also do in the simulator  if you hold option  you'll see that my cursor flanked by a second circle. And these represent two fingers. So you can actually mimic the idea of pinching, even though you can't touch your laptop screens. And if we do this, we can zoom in on Rob's denim shirt atop denim shorts. And or we can zoom out until this image gets super super small. Much like you might pinch or zoom in maps, or Google Maps or the like. So, how would we go about implementing something like this? Well, let's take a look at some basic building blocks. And we'll see some similarities and some differences. This is the more complex of the ones we looked at last time. So AppDelegate is a good place to start. Main dot M never seems to have anything of interest, so we won't even glance there for now. Does anything look anomalous? New? Different? In this file versus past examples? This is the AppDelegate.h file. No? Nothing magical there. This is just a boiler play code that you get with the single view application. How about the dot M file if I scroll down. Looks like this is the only method. Anything interesting, new or different there? No. But it seems to be this guy as usual that's kick starting the process by assigning to view controller, a newly allocated controller. It's being initialized with a nib view controller. There's no file extension, but recall that that's by default by referring to the dot XIB file that we had for some time now. And then finally we're making it the key window and visible, which means foregrounds, whatever the contents of that nib were. Well, what is that nib? Let's take a look in the XIB file and we see Rob. For a moment in flash, for just a moment, because that's actually  there's a couple of objects layered on here. And we can see this by zoom in and I click on view. Recall that view  a UI view is is the rectangular shape that we typically lay down. And we have an image view. So, this is actually a different class that we haven't seen before. If I pull over inspectors over here on the right, and choose my identity inspector, you'll see that this is a UI image view. And this is like a container for actual images. And those images as we'll see in a second are going to take the form of UI image objects. So let's actually see how we now started listening for event atop Rob's single photo there. Well first, let me expand supporting files. There is the photo, Rob.jpeg, that I configured here. And indeed if we go back to the inspector just to confirm, let me go up to the attributes inspector. The fact that it says rob.jpeg on the top right corner, that just means that's why the imagery was displaying that image. So no magic there. So is the complexity must be in this guide, no, not in the view controller. H or the one remaining candidate view controller. M. So let's see if we can't wrap our minds around what's going on here. First, a couple of teasers. So this up here is an example of what? What object of the construct? Yes? Yes, so it's a category. It's a nameless category because there's nothing inside the parentheses. And it's a way of sort of creating the illusion of privacy and objective C whereby we have apparently a private data member called a CG point underscore translation. And CG point is actually something from the core's graphics library. So CG, core graphics, this is referring to Apple's support for two dimensional graphics. And we'll see that this is actually a primitive of sorts. It's not actually an object because a lot of the code you're about to see in two dimensional graphics actually has its origins and seeds. So we're going to start seeing some commingling of objective C and C, which is the language they'll call you to look at when Rob was at the [inaudible] a few weeks back. So we have a couple of properties in here. One is a float called scale. And one is an image view, a UI image view called image view. And we'll come back to that in just a moment. We seem to have a couple of private methods here, one is called handle pan, so moving left to right, up, down. And handle pinch, which is the two finger gesture. So that's just setting the stage now to listen for those events. And if we scroll down here, what seems to be going on? But when is this  yes? Is there any reason to use an instance variable rather than a property? That's a good question. What was the motivation for this. You can still do primitive. Short answer  I don't think  yes? Yes, no  that's true. But I'm  at the same time not doing the same when it comes to scale and image view necessarily. Let me think about why we did this the way it is, but short answer  doesn't matter in this way. We don't need the functionality of the setter or getter. Pretty good question. I'll come back to it. All right so, in initWithNibName. This is the first method that's invoked here. And the ininitWithNibName seems to be preparing a few things. So one it's calling the super class, which is actually doing the loading from that. XIB file, which is the normal default case. And then we're apparently setting a property called scale to 1.0. And that's just a default reminder that by default, Rob is at normal scale. A hundred percent X, a hundred percent Y  there's no zooming in or out. And the translation X and translation Y is referring  oh, this is why. So, the reason that I'm using the  so CG point is actually something called a C struct, which you may call it glancing at and see. And just kind of like an object that doesn't have methods associated with it. It's just a data container for data. So problems actually arise because Apple goes to use the. Operator when it came to properties. But the. Operator's is also used for structs. So doing it this way ensures there's other clarity as to what's going on. In this particular line here, that's highlighted in blue, I'm accessing the X member of the CG point struck. And I'm doing then the same for Y. So things get a little messy if you start commingling the two features. Get back to this. Okay, so translation X, translation Y. A translation is just a shifting. Up, down, left or right or some diagonal. And this is implying by default. Rob has not been shifted up, down, left or right. He's just smack dab in the middle of the screen. So these are initializations of variables. So now, a few things are going on. There's a handle pan method apparently. There's a handle pinch method. There's a view did load, let's actually go to view did load down here and let me hide this so we can just focus on these three. View did load recalls loaded, once the nib has been loaded. The view is ready to go in memory. And as the common suggest, we're listening for two things. A pan from left to right, or top to bottom, or bottom  or top, down. Or a pitch with two fingers. And this is code quite like we saw last week. We initialized a certain type of recognizer. We initialized it with a target that has to be self in this case. Self is referring to an object of what type at the moment. Who is self? The view controller. So presumably whatever method, we are telling recognizer to invoke when panning happens is somewhere in this class. And indeed it's higher up in the file. And in this selector syntax is just our way of saying, call the method handle pan. And call in just means it takes that one argument. And then over here, what are we actually doing? Well, notice that self. Image view is our property that maps via interfere builder. I drag and drop the little blue line connecting IB outlet to my nib. This is saying, add that recognizer to that view object on the screen. So that is the rectangular shape that's going to listen for this pan gesture. And pinching, essentially the same thing. Any questions on how we set that up? Thinking back that again the structure is the same as last week. No? Okay. All right. So now let's look at the part that does all of the thinking. So handle pan. This is where it gets a little complex. But this is just the result of reading through what exactly each of these functions does. A lot of this is again C. And the first thing that happens here is that we first request from the UI image view, that container containing the image. Something called CG point translation. So this is essentially 0 comma 0 by default. And then the next line we're making an AffineTransformMakeScale, which is essentially saying by how much do you not to grow or shrink Rob along the X and the Y axis. And then we go ahead and ask to make a translation. Translation refers to by how much you want to shift Rob, to the right, to the left, up or down or along some diagonal by adding those two axes together. And then lastly, this last line of code actually applies that transformation. That changing in scale, bigger or small sand that shifting, up, down, left or right to whatever the object is, which is again, that UI image view. So, those several lines of code which are at each point essentially declaring a C struck. The C struck  a C struck that's being populated by the return values of these functions on the right hand side. They're then being applied in this final line. So what is the role played by these last few lines down here? Why are we not done as soon as we we apply the transformation? Yes? [ Inaudible ] Exactly. Good. Because we're doing some additive math, especially when it comes to the translation, we're taking into account where Rob began on the entire screen. So if we wanted him to not snap back to the default location each time you drag or drop him, we have to simply update those local instance variables. Yes? [ Inaudible ] Good question. It does expire several times otherwise if  when I clicked on Rob's face, I'll be in a simulator there. You wouldn't have seen anything happened until I let go. So it does fire at a particularly fast frequency so that you can respond essentially pixel by pixel. Good question. Yes? You can change the rates. The default is set by default but you can override it so you can respond in different ways. Much like the long press. By default, it roughly two seconds before Rob's face would have triggered that UI alert view last week. And that too you can raise or lower programmatically when declaring the gesture recognizer. Good question. Yes? Uhhuh, say that again? So we're called, these are not IB action. So IB actions are how we declare methods inside of a class when we want objects inside of a nib to talk back at them or more generally for UI views to talk back at them when a user interacts with them. In this case, it's the gesture recognizer, which is a class that Apple has provided with us. That is responsible for invoking this methods. So it's not quite the same use case because these messages are being passed by this recognizer class. [Inaudible] in IB outlet property. So typically, if you want to connect your code to an interfere that you created with interfere builder in a. XIB file, then yes, you do exactly that. And that is the reason why we scroll up to the part that we glossed over earlier. I have two things declared as properties. One is is the scale, which as we'll see is just a way of remembering when I pinch, what the scale factor is for Rob. If it's not 1.0 by default  in image view is very typical. Notice, that we have IB outlet here. And we see this in a number of examples in past weeks. This is my mechanism for actually linking my code to the UI image view so that I can actually apply that recognizer and listen for those finger touches. Good question. So, pinching is going to be pretty much similar in spirit, even though some of the functions calls will be a little bit different. Let me scroll this over just a bit. And handle pinch is method that's going to get invoked when you're using the two finger to go separate or closer together. And now we have this first. I'm declaring a CG float struck. So again, here too, it looks like a class. It it looks like an object thereof. But this is again just capitalized to be consistent with Apple's tradition for C [inaudible] structures. This is a CG float, which is just some representation of some floating point value. CG affine transform scale is doing a line of code similar to before where we take the current scale and multiply it by some factor. And notice that the factor has been passed in to us. So one of the things this recognizer does is it figures out how far away did your fingers move in that split second of time. And then it forms this method what that difference is so that you can scale accordingly. Then if we looked down here we're doing a translation. This time we're not actually moving Rob because we're  we only want to move Rob when we're panning, not when we're pinching. So he's going to stay put but grow from wherever my fingers are moving closer or farther away from each other. And then we apply these two things again much like we did previously. And then lastly, all we do is remember that change in scale so that when I do it again, he doesn't snap back to the default 1.0 resolution to start anew. All right, any questions then? So we've seen some buildings blocks now for swiping, up, down, left, right  for touching, for pinching, for clicking and dragging. And so, with those, for your third project, if you choose to do something in iOS that actually has UI interactions beyond what's possible out of the box with interfere builder, realize that these are the basic building blocks. Even for say, a simple game. We'll put these to the test later tonight when we implement an age old games of sorts. All right. And you might see [inaudible] to right there. All right. So, questions on the basics of graphics before we move onto things that are useful to have in your tool kit. But then we'll come back full circle to the application of two dimensional graphics Actually moving on their own without human interaction. Okay, so a design question then. So, totally changing years for just a moment. And localization refers to what process when writing code? Okay, internationalization. So not just naively assuming that everyone of your users is going to speak English and read English but rather might have some other native tongue. And you might want to cater to that audience that actually download your user app, can understand your app. Whatever the reasons. But this is problematic because we've gotten to the habit thus far of writing quite a lot of code. And what's essentially English, since Apple came from the U.S. but also, quite a lot of strings. Quite a lot of NS strings inside of double quotes. Maybe prefix with an at sign. So this is kind of problematic. Because I feel like if I want to suddenly support Mandarin or Spanish or any other language to which I might want to localize high application, now I have to do a whole lot of copy paste. And any file that has a quoted string, like hello world, I'm going to apparently need to copy my view controller. H and maybe make a separate one for each language. View controller. M, a separate one for the languages. Like, surely, this isn't the way. Because if there's some 50, 60 languages you might even want to support, I mean, that's a nightmare to have that much code lying around. If only because now if you want to make a change, you have to make it in dozens of places. So what's a smarter approach? And let me [inaudible] this with someone who's never internationalized an application before. How would you go about solving this problem? All right. [ Background Discussion ] Yes. So that's exactly right. But the principal that I'll highlight there is the fact that you're proposing that we factor out the strain. So you could write all of your code in English or pseudo English, an objective C or C, whatever the language is. But if you at least factor out the strains that have to change based on the users end language by putting them in some central file, now you can keep  separate your codes, your business logic so to speak from your actual data, in this case, the streams that the user sees. So, you're indeed right, the way Apple typically does this for desktop or iOS applications is that you have a P list file, which is just an XML file underneath the hood. But so far as we care, it's just a text file that we can therefore edit. And if we have after separate file for English, a separate file for Mandarin, a separate file for Spanish, we can essentially tell iOS, the operating system, depending on what language the user's iPhone or iPad is in, load the appropriate key list file for me. So, in fact, you've seen a few different things. We'll use a file that typically ends in dot strains. But it's the same exact idea. It's even simpler than a P list and that we just write things in the form of text, no XML whatsoever. So, let's go ahead and do an example here. Let me open up X code. Create a new project, which we'll do a single view. Let me then proceed to name this, let's say, Hola 1. I will bias things toward English and Spanish for now. I'm going to go ahead and leave automatic reference counting checked. I'm going to leave everything else unchecked. I'm going to go ahead and click next. I'm going to go ahead and save this on my desktop and now I have the simplest of applications, which will call if I run it, just gives me a big white box in the form of an application that looks like this. So very underwhelming. But let's make it a little sexier by going into the nib file. Let me go ahead and drag a label into the middle just so I could support iPhone four and iPhone 5's. Let me go ahead and click down here if you haven't noticed this control bar, and turn on a constraint called vertical center. This will ensure that whatever simulator you're using or whatever device you're using, at least this text will be vertically centered. And by default, let me just go ahead and make the American centric version  hello world. All right. So now notice what I have on the lefthand side of my screen. All of the familiar files. The program happens to be called Hola, but that's just because I wrote that and nothing has been actually been internationalized yet. But those are all pretty much familiar files. And particular notice there's just a single nib file. But if I now want to localize this application, we can do the following. And unfortunately this feature changes location with every version of X code it seems. But if I go ahead and click on the project on the top left, then click on the project to the right of that, you'll notice down here that there's a screen in related to localization, a.k.a. internationalization. And if I go ahead and click the plus here, I have a whole bunch of languages that X code supports nicely right out of the box. I'm going to go ahead and choose Spanish. And if I zoom out I'm now being prompted to do a couple of things. Choose files and reference language to create Spanish localization. So it turns out that by default, there's two different files that can take on some other language. One is the nib file apparently. And one is a file called InfoPList.strings. So, I'm not going to touch the latter just yet. I'm going to uncheck it and come back to that. But I am going to tell X code to localize my nib file. So if I go down here to finish, what I now get is both English and Spanish. And if I go back to my nib, notice that by default, I still see hello world but notice what's different about the nib on the top left. Yes, it looks like its become a hierarchy of some sort. If I expand this triangle, I seem to have English, which is what I had a moment ago. And then I have Spanish, which is apparently the same. Okay, so it actually hasn't done any translation for me. That's sort of human to actually do. But I can go into this nib now and I can say something like, hola, mundo. Change it there. Save it, and now I have my English version and my Spanish version. So let's see what now happens. I'm going to go back to the simulator. Or rather let me go ahead and [inaudible] the simulator by running the code. Its been built. It's being installed into the simulator. And when it comes to the foreground we should see hello world. Now, let me disclaim. About every 5th time I try this on different computers, it doesn't work. So if it blows up, realize that I've should a disclaimer, which means it's okay. But if I now go here, these are just all the applications we've been installing in recent weeks. I'm going to right click over to the settings. And if you've never done this on your phone or iPad, you can go to general international language. And I'm going to choose Espanol for Spanish. Done. It's going to change language dot dot dot. The next code is going to crash because it doesn't like it when you do that when it's still running. But I'm going to go ahead now and rerun the simulator. And now we have a Spanish version of the application. So the only thing that's changed, crash aside, is that I changed the settings in my application to actually be, Spanish instead of English. And if I went back to English, you should hopefully see hello world instead. But a couple of things haven't changed. In particular, what's the name of this application apparently. So it's still Hola 1. So irrespective of the language, my phone is configured with the application, which is still the same. And maybe that's a good thing. Maybe you want the game to be called Angry Birds no matter what the language is actually is. Or maybe you want to localize that too. So you can do that in different places. So let me actually go ahead and open up a second example here whereby we start fresh, single view application, Hola 2, will be this application. And save it on the desktop. And let's do something that's almost the same but this time I want to do a little bit more in code. So I'm going to go ahead and open up my nib file. This time I'm going to drag my label. And I'm not going to hard code it into my nib. Because we're called that if we do a little bit more programming, we can actually control that label programmatically from code. So if I want to do this  let me make sure things line up with the online codes  so that you can play along at home after. If I want to actually do this, what's the first thing I need to do to wire my code up to my nib file? So all I have is the empty boiler play code thus far. Yes? Okay, so I need to create an IB outlet, which likely belongs in what file? Okay. So, somewhere in the ViewController. And early on we're called that we put almost all of our properties, just by convention, into the dotted H file. But then gradually last week we started moving more and more of our properties and method declarations into the dot M file. The implementation file, just because there's really no reason to inform the whole world what our private implementation details are. So I'll go ahead and open up ViewController dot M. And I can implement this inside of my nameless category. So I'm going to declare a property with a view attributes. But we will come back to that. It's going to be a UI label and I'll just call this label. Now I need a couple of more things. If this is going to be an IB outlet, I need to say IB outlet. And what attributes would be appropriate for this outlet, for this IB outlet? Well, one is always easy. We haven't seen atomic, so non atomic, I think is fine. We're not writing multi-threaded code out here within this application. Read only or read write. The goal is to recreate the hello world application by this time in code telling it what to say. Either hello world or hola mundo. Okay, so read write since I want to be able to change what it's pointing at. And then lastly, I can actually go with week. So we haven't spent too much time on this but we're called that strong versus weak somehow relates to how the pointers are going to be dealt with. And in this case, weak suffices because all I need is a pointer to a UI label. But I'm not the owner of that UI label per se. The owner is really the nib file. And when the nib is loaded, it will take care of [inaudible]. That the ram that's necessary to store that label on the screen will be allocated by it. I am just some other guy, ViewController.m, that similarly wants to talk to that pointer but it's not really mine per se, so weak suffices. Someone else owns it. I did not instantiate it myself. It came from the nib. So after this, I now have programmatic access to the label. So what do I want to do? Well, I want to get rid of the [inaudible] receive memory warning. There's not much we can do if this application runs out of memory because there's terribly little going on, just that UI label. And I am going to put some additional code into viewDidLoad. First, again by convention, I'm going to call the parent classes, viewDidLoad method, whatever that happens to do. And when this view load  so when the nib is loaded from disk, and the rectangle is constructed, and that UI label is placed in the middle of the screen. And I want to do one configuration detail, namely, self.label.text is what's actually inside of that label. Is going to get. And this is the new part, NSLocalizedString. And now according to X codes prompts here, it wants a key and or a comment. So I somehow need to provide it with an identifier for that string. It doesn't want me to put, for instance, hello world, per se. But rather a generic key that's going to be defined in two different places, two separate files, so that I can look up that value dynamically. So, comment, I'm going to actually leave nil. Comment is just for really the humans doing the translations. You can use tools to automatically generate a file. We are about to generate manually, so that if you or the programmer, who maybe only speaks English, but you want to tell other developers who actually speak multiple languages, what this string represents. You can do it in the form of after comment there. So that when they automatically generate the file we're about to generate manually, they know what you mean by that key. So I'm going to choose something arbitrary but sensible, like, greeting. So quote on quote greeting, is not what I want the user to see. It's just going to be a key into a table of strings. So to create this I'm going to go up to file, new, file. And we haven't seen this one before, but if you poke around, you'll start seeing some other useful things. If I go to resource, notice there's a few resources here. Property list, we've seen before. Strings file is another. And according to the description, it is an empty strings file. It's just a text file. So let's go ahead and click next. By default, I'm going to call this Localizable.strings. And X code knows by default to look for file by that name. And if it's present, go ahead and allow the user to just find multiple languages strings in there. So I click the create. And now I have this text file over on the lefthand side. Notice that there is just some generic comments at the top. And it's in here where I can now define some key value pairs. All right? So now, if I want to go ahead and define the key value pair, let's go ahead and define what greeting has to map to what. Hello world or hola mundo. And then we're going to need to do that  not in the same file  but in two different places. So before we do that, let me go up to my project settings as before. Hola two is the project. And let me go ahead and add proactively, Spanish. Unfortunately by default, X code only seems to know about these two default files. ViewController.nib and InfoPList.strings. We're not doing anything with the nib this time. So just to keep things clean, I'm going to uncheck that. InfoPList.strings we'll come back to. And now I have Spanish language. But unfortunately, I haven't solved the problem at hand. And this is just an [inaudible] UI decision. Notice on the right hand side here, if you want to localize a .strings file that I have created myself manually, unfortunately you have to click this big button called localize. And here's where I'll be prompted, oh, do I want to localize this file into which language? Spanish. Now we'll go ahead and localize. And now  that did not behave  oh, there it is. By default, X code does not check both boxes. So if we now check English and now go over here on the left, Localizable.strings has both English and Spanish forms. So if we fast forward now to the climax of this example, what we'll see is an example that has both the Spanish version and the English version exactly as follows. In Hola two, we have supporting files. And if we go to Localizable.strings, specifically the English one, notice that again, this is just a mapping of keys to values. Quote on quote greetings equals quote on quote hello world. Notice that it's not an NS string. These are C style strings now, so there's no at science involved in this file. But they do end with a semicolon at the end. If I go to the Spanish version, the key is the same, so you don't localize that. But the value does change. And so, because this file is called Localizable.strings, iOS will load it automatically for you and use that when you call the function that we did earlier, called NS localize string. And there's one last thing I did here in advance. In this file, which to date, we have not actually looked at. InfoPList.strings. According to the documents, if you define a key, called CFBundleDisplayName, you can also change the name of your application programmatically. So in this case, I want my application to be called Hola. But if the user is English speaking, I want it to be called Hello. So no more Hola one, Hola two. This is the formal name for my application. If I go ahead and run this, I'm still in the simulator here. So we should see  now the second version of this code. Hola mundo. And if I now go back to the desktop and take a look at the program's name, it's Hola. If I go back to English, that's changed to Hello, and the string should go to Hello world. So, sort of lesson learned here, especially if you're planning to do something for the app store. And you actually do want to appeal to multiple languages, this is the sort of thing where it's good to start designing your strings file now so that you don't, after writing 2,000 lines of code, have to go back in and then start ripping things out and redefining key value pairs. If this isn't a problem, if you have no expectation of localizing, not a big deal. But it is this easy. And it's a lot easier to do it in the beginning, even if you just have a Localizable.string with only English. Because just think how trivial it is if you make a friend who speaks Spanish and he or she can then translate your whole app for you just by your sending him or her that text file to send back to you, the importance of a project. Yes? [ Background Discussion ] Ah, good question. By default there's still one primary language. In this case it's English because that's what I started with. So what would happen is that you would get the English version by default. If the user has chosen some other language that your app doesn't explicitly support. [ Background Discussion ] Good question. Most likely. If Mac OS is configured for Dutch and therefore X code is as well when you download it from the Dutch app store, I believe that's what will happen. But I've not had occasion to test that. Other questions? All right. So, where can we take things from here? So I propose that from here there's a couple of gaps we can fill in before moving onto the climax. Albeit a 1980's climax of a two dimensional game. But sequel lites. Let's add one other tool to your tool kit. What would sequel lite all about? Okay, good. So it's a flat file relational database. So this is just a fancy way of saying, there's no server involved. There's just a big binary file that can sit inside of your application. That can create the illusion of a database to your application, namely a sequel database. And a sequel database allows you to do searches and queries along the lines of select and insert and delete and update. And even if you're not familiar with that, those four letters together compose a paradigm called CRUD. CRUD for create, read, update, delete. Which is a very common paradigm for talking to a database which essentially lets you do anything. You can read from it. You can write to it. You can update things, you can delete things, you can store data in we write fashion. So why would you care to use sequel in this database language as opposed to just using a P list, like we've been using for the second project. Or even .strings file, you just have a list of strings or some other file format altogether. Speed? In what sense? [ Background Discussion ] For sure. Certainly for large data sets for you have thousands, tens of thousands, hundreds of thousands of records. If you stored it in a P list, well, by default that's just an XML file. So really, it's just a big long list. So if you were to do searches on a property list, you essentially devolve into linear search. And in an worst case, maybe the structure you're looking for in the dictionary is at the end of that P list file. So it's going to take you thousands or tens of thousands of reads in order to find the word you're looking for. By contrast, if you use an actual database, whether it's my sequel or oracle in the real world, or sequel lite in a constrained environment like this, you can say something like, select the word that starts with Z. So I'm using sort of pseudo code verbally. But you can express yourself more precisely. Select the word that starts with Z and what sequel lite can do for you, if you tell it in advance, is it can give you, what are called, indexs. Essentially, tree structures that have been saved to this file that once loaded into memory, allowed you to search this file much faster than say linear search would allow you to do. So at least for large data sets, it allows you to express yourself a little bit more precisely than just iterating over a big list of things. And to get that data more quickly. Unfortunately, for those of you who are familiar with sequel, the price you pay is in shear complexity of the codes. Since to date, it's still a C library, which is a pain in the neck to use when doing something as simple as we just described. But nonetheless, so that you have this expressive capability at your disposal, particularly for your third project of doing something with a decent sized data set, let's take a look at this example, called sequel lite from tonight's code base. AppDelegate  look special? No, nothing new there. AppDelegate.m, anything going on here? Nothing there. So hopefully the interesting stuff starts in the nib file, okay. So, apparently this app has to do with cities. Known as just again, stupid boiler plate patterns of any UI table ViewController. So, this just means the application has a table ViewController, and let's actually spoil the results. Let me go ahead and run this application and see what happens inside of the simulator. And what we can see here in the simulator is that all this application does is it opens the contents of a sequel lite database called small.sqlite, as we'll see shortly. And it lists those five words. From the small P list file that we gave you for the most recent project. So what I did in advance was I wrote a little script that converted that property list file into a binary sequel lite file. It's pretty easy to do. And then I included the small.sqlite file inside of the project by just dragging and dropping it from my desktop. So, how is this actually behaving in this way? Well, let's take a look at ViewController.h. Nothing going on there. So all the logic must be in ViewController.m. So, first of all, notice that I've declared an NSMutableArray as a property called words. And this is just where I'm going to store my words when actually using them. Much like you probably have for evil hang man after you've loaded the property list. And if I scroll down here, let me get rid of one remnant there. I have in initWithNibName. And this is where the nightmare begins. So, and I say this, because it's just a pain in the neck to actually code sequel queries in this way. But, this is the way it is, not only in objective C but in some other environment as well to this day. So, notice I'm first initializing myself with the nib name. Whatever that was, by calling the parent class. Then I'm declaring an NSMutableArray here and assigning it to my property. So I just have an empty changeable array. And now, what am I doing in English or sort of semi technical English with this highlighted line. What's apparently going on there, even if you've never used sequel lite before? Yes. Good. So I'm creating a pointer called DB to an object of type sequel lite. Whatever that happens to be. It's some kind of structure presumably. And then in that next line, notice I'm going back into objective C mode. The highlighted line is effectively C. So here I'm declaring a path variable that's the result of looking for the file called small of type sequel lites. So this is just a fairly robust way of saying, give me the path to the file called small.sqlite. And notice over here on the left, that's the file I promised that I dragged and dropped into the project. It's a binary file. So clicking on it won't actually show me the contents. Now here, is a bit of syntax. We haven't seen too much. But you might recall from Rob's lecture a few weeks back. Sqlite3_open is a C function that opens a database connection. So, database, notice that path is of what data type in this point of the story? It's an NS string. But sqlite3_open, perhaps take my word for it, is a C function that has no concept of objective C classes of observe. So we essentially have to convert path from an NS string to what's called, what most people call a char star. A raw C style string which is just the dress of a bunch of character. A character array. And so what this line is doing is exactly that. It's opening the file call  that's at that path  and storing it inside of the DB pointer. Okay? What's happening next? I'm selecting all words. So, this is what I meant earlier about the expressiveness. This is a sequel query. And this file at the end is only going to have one such query. But again there's other key words like delete, update, insert, any others, select is the operative word here. Here I'm declaring an NS string called sequel. In the next line, I'm dropping back down into C, declaring a statement. And then in this third line I'm calling sqlite3_prepare_v2. This is what happens when you overall plan your functions ahead and names get like this. And then I'm passing in a few values. Again, converting from a C  an objective C style object to a C style string. And let me wave my hand at some of the details there. But what this just means is get ready to execute the previously declared query. Select star from  select word from words. So what is words? Words, again, is the database. Or specifically, it's a table inside of the database. Like an excel spread sheet. And word, specifically, is is one such column from that spread sheet. So this is a super simple database. It essentially is an excel file with a single column A, if you will. And column A is called  just because I named it such  word. So it's not even that interesting of a database. Yes? [ Background Discussion ] Exactly. So you don't strictly need to specify the database name. You don't need to say database.table if it's obvious from the context. And in this case, you can infer it from the context because when we open the connection, we open the connection to a specific database. So that part has already  that question has already been answered for the library. So now down here is where we are actually fetching data. So by calling sqlite3_step, passing in that statement that I've prepared in the previous line, If that equals SQLITE_ROW  so, in other words, if that function returns to [inaudible] row in the form of a structure, I can then proceed to do the following. This next line of code gets the 0th column or the 0 cell from that  0th column from that return cell. And then in this next one, I convert the string that I've gotten back to what kind of object? So in NS string. And then the last line, I'm finally back to more familiar territory. I'm adding that string to my property, which is a NSMutableArray called words. So again, the difference here, for those less familiar with C is that in C there is no notion of an object. There is no notion of a class. It's not an object oriented language. So to implement the idea of a string, what C does is it uses an array. So, a chunk, chunk, chunk, chunk, chunk of memory. And then to represent the string, it uses a back slash N, a null character at the end of the string. And then it gives to you the address of the first character. So in C, if you know the address of the first character, and you know that there's guaranteed to be a null character at the end of the string, you can figure out how long it that string is and what the word being expressed actually is. [Inaudible] where whatever it is in the database. Objective C by contrast using classes and objects. So maybe that's how a string, an NS string is implemented underneath the hood, we just don't know. So what these several lines of code are doing ultimately is toggling back between these modes so as to use the C base sequel lite library, while still using it in objective C context. And then lastly, that we close the database connection. And the rest of the code here which we won't trace through in any detail, is pretty much the same as last week. The rest of the code just has to do with the UI table view and somehow defining the cells that you see when asked what goes in row 0. What goes in row one. What goes in row two and so forth. But there's one thing I had to do behind the scenes. Recall that for quite some time under frame works, we had just UIKit.framework, foundation.framework, CoreGraphics.framework, which we finally started using tonight. Notice that in supporting files, there's something similar in spirit, but it's a C library. So it's called a dynamic library. Sqllib  sqlite3.dylib. This is a file that I did not drag and drop into may project per se. Rather, in order to use this library, and potentially any other libraries that Apple provides, I went into my target. Went to build phases. Went to link binary. And here is where you see the list of libraries that your application is using. By default, we've always gotten those three objective C libraries. Today I needed a fourth library, mainly the sequel lite library. So to get there, I had to click that plus icon and then look through a list of libraries. And you'll see there's an overwhelming number of options. Suggested of how much more you can do with the environment. If you really dive in deeper, this happens to be a C based library. And what do you think is inside of this library? What is the point of adding this row to this configuration table? I wrote Sqlite earlier, right? I wrote the various function calls. Why do I need to add something like this? What must be inside there? What's that? All the function definitions, so the actual implementations. The only thing I had to do even though we glossed over it earlier, is in my ViewController.m file, I did import this .h file, but in a .h file is not the implementation of some function. And typically is in some other file. So, if I actually want the bits, the 0's and 1's, that collectively compose the Sqlite statement query, the close query, the open query  I need to actually import those bits at link time so to speak. And the means by which you do that in X code is via the project's own properties under build phases. So, FYI. Yes? [ Background Discussion ] Short answer  not as cleanly as would be ideal. Rather there's an even higher of layer of abstraction called core data, which is actually a pretty raw topic onto itself. But it's essentially an abstraction layer on top of sequel. Or it can be on top of something else potentially that allows you to define your entities and your relations without going into the depths of sequel. All of that would be generated for you. So, short answer  no. No wrapper in objective C rather apple leap frogged and went one level higher. Quite possibly. Yes. I've not used one, but there's not one that comes out of the box officially. Good question. So wonderfully useful, but also takes some getting use to. So, keep that in mind. But much more powerful than something like the single key list file. So let me open up a little teaser here. Some of you may recall or have at least heard of a little game, that for many years was amazing. And it looked like this. Let me go ahead and run this. I'm going to put the iPhone into a landscape mode this time. And notice that the computer is playing on the left. And the human, I'm playing, on the right. By moving the cursor or my finger, really, up and down. If I do this, I can do this all day long. This will just play and play until I do something stupid, whereby if I forget to move, now he has the points. So, why don't we go ahead and take our fiveminute break.  I really lost fast there. Why don't we take our fiveminute break here and when we come back we will implement pong together. All right, so first let's resume by lowering expectations. This is an example called paddle, which is among tonight's examples, whose sole purpose is to do this. But it's a good building block if we actually want to get to the point of actually having a bit of  AI, if you will. You'll notice if you play the pong game as its been written, the computer will never ever lose. Because it will see the code is written in such a way that the paddle always move to precisely where the ball is no matter where you hit it. So, only the human can lose that game. But, we'll start by at least making our own paddle here. The cursor there on the screen is what my finger would be if we weren't doing this in the simulator. But first, we need a little bit of context. So let me switch over here for just a moment. Just to paint a picture of how your mental model should be when it comes to graphics. So, correspond graphics is the context. We've seen this library included for every example we've done thus far. But this is the first night where we're actually using it. And what's worth keeping in mind is this system  got to get better at this  this coordinate system here. So I looked for newer image, but even Apple documentation uses like the iPhone three for this example. But it's really just to paint a picture of the coordinate system in iOS. Which is this plain, where we have X coordinates on the right, Y coordinates on the vertical. And this is just the take away here is that the coordinate system begins on the top lefthand corners. So, ten comma ten means ten over and ten down. Not the opposite as you might know from say typical [inaudible] coordinates and algebra. So, the catch is  as Apple's hardware has advanced over time, that resolution have started to change, right? There was the retina display and the iPhone four, when the resolution essentially doubled. And unfortunately, this could have broken a whole lot of applications. But Apple actually anticipated something like this in the sense that you don't think of graphics in the two dimensional world of iOS as pixels, but instead as points. And a point is still just a dot. But it might be one pixel, or maybe it's four pixels. It depends on your perspective. So they introduce this layer of abstraction called points. So that you're respective of the actual resolution. The operating system will double your graphics as needed or shrink them as needed. Now this has  it's a two edge sword. It's on the one hand, super convenient, on the other hand if you've ever used an IO  an iPhone only application on an iPad, it just looks kind of ridiculous when you zoom in at two X. But that's really the only alternative would be to not let the user play it at all. So now if we scroll over to this system here, you'll see the iPhone four and the iPhone five. So the annoying thing here is that Apple didn't just double the resolution, they just kind of stretched it a little bit. So there were a few more pixels now on the screen. So this was more problematic. And there's still some apps out there that you might have on your own phones that now have letter boxing on the bottom or on the top with just black bars. If you have an iPhone five and you're using somewhat older software that the developers hadn't updated. So in this case, the number of points on the screen has actually changed. It's still 320 pixels across, but it's now 568 tall instead of 480 tall. So this is why Apple, as in aside introduced something called auto layout with the most recent version of X code. And we saw me use it ever so briefly earlier. When I said to vertically center the label that I dragged and dropped by choosing a vertical constraint. This is the new means by which you can essentially lay things out dynamically. Unfortunately it doesn't quite work as easily. If you're implementing something like Angry Birds or something graphical where there's a pixel precision when it comes to your graphics. So some people actually have to use different graphics for different modes. And that's why we started to see more [inaudible] among the supporting files and all the projects. One is a bigger splash screen. One is a smaller splash screen depending on the device that someone's using. So it's starting to get a little more android like in its new sense. So we'll see what happens next with the iPad, which is like, would become, right now before long as well at a higher resolution. All right. So how do we go about implementing something. It's relatively straight forward as this. There's some new ingredients. But what are some now familiar ingredients if we want to implement something like this? What concepts or code can we steal from recent examples to implement this paddle? The sole purpose in life is to go up and down. Yes? Yes, so maybe a pan gesture recognizer so that we can actually detect the user moving his or her finger up or down in this case. And just ignore their finger if it moves along the leftright axis. All right. So, let's take a look at how this begins. AppDelegate? Same as usual. AppDelegate.m, same as usual. So, no magic there. So everything must be going on in  interesting. I have a new file altogether this time. A pair of files called PaddleView.h, PaddleView.m. Let's take a look at the H file first to see what this class is. And it looks actually pretty trivial. So I'm just importing new UI kit, which is pretty typical. And then I'm declaring a class called paddle view. And it's of type of UI view. So this is the first time we've actually declared in code our own UI views. We've had UI view controllers, map main ViewController, flip side ViewController, ViewController. But we've not declared our own UI views. To date, where of our UI views come from? Often the nib file. By dragging and dropping. And in our no nib example, a couple of weeks ago, we did instantiate UI view objects ourselves in code manually. But even those were Apple's own UI views. UI button and the UI text field. So this is the first time where we are defining our own view. Because Apple  iOS doesn't come with a white rectangular paddle. So we have to create that somehow ourselves. So the means by which we've done this in the .m file is fairly simply by taking advantage of a method that is called automatically, whenever a UI view object is instantiated. This is essentially an analog of like viewDidLoad. But that's at the UI ViewController level. Now we're at a lower level at the UI view level. So draw rect for draw rectangle is what's called when it's time to initialize one of those little widgets that we've thus far been dragging and dropping. So here again, we're commingling some C code and some objective C. CGRect is the name of a core graphics rectangle, which is a C struck. A container with just data. No methods. I'm going to call this square. And on the right hand side we have a function called CGRectMake which just returns a C structure. So a container with a few fields. And those fields are apparently four in number. The first two are going to be initialized as 0. Third is 10.0. And the last is 60.0. Any guesses as to what those numbers are referring to? Close. Not color, in this case. But dimensions. And one other detail  the XY  the initial placement of this thing. So, 0 comma 0 is just implying that it's not going to be offset at all. It's just going to be in the top corner of whatever rectangle we're creating. The width is going to be ten points. And the height of it is going to be 60 points. All right? But that's not enough. Now we've just created essentially a rectangular widget. Something that could be  if Apple really liked our paddle, dragged and dropped in some future version of X code, right? That's really all we've done here. But there's more complexity certainly for something like the UI button. But now let's see how we use this. In my ViewController.nib, notice I've done nothing except change the orientation. So if I actually click on that thing and go to the attributes inspector, one of those various check boxes and drop down menus would let me change from portrait to landscape mode. And that's the only change I made in addition to then changing the background color from that default of gray to black. So this is going to be my game board, so to speak. But if I now go to ViewController.h, nothing interesting in there. So the remaining magic must be in here. So notice inside of my ViewController, I'm declaring a property that's of type paddle view. Which is my own class that I created. And it's going to be called PaddleView. Lower case P, capital V. Now let's take one step back quickly. Where did PaddleView.h and .m come from? Well, we haven't done this that often. And we did do it earlier with the strings file. Earlier when creating this, I went to new, file, and then I just went up to [inaudible] touch. And started with an objective C class. Went to new. The class name I gave it was PaddleView. And I didn't have to send it from NS object. I had it to send from UI view. When I hit enter earlier, I got those two files for free. And that's when I dove in and then began to implement DrawRect. All right, so now, in this file, we have a few methods. In initWithNibName. And this looks pretty familiar except for some new core graphics code. So in initWithNibName is again what's called as soon as the nib is loaded from disk. But that nib by default is just rotated in landscape mode and painted black. Now I want to do one other thing to it. Self.PaddleView, means assign to my property what? The result of allocating a PaddleView object and initializing it with a frame. So here there's a bit of a dichotomy. Now I am initializing this PaddleView object to be inside of a canvas. So whereas before, if you're familiar with Photoshop, I created like an image. Now I'm creating the canvas on which to place that image. So, the image can be offset in the canvas itself. The canvas can be bigger. And in this case, the canvas is going to have this image view, this PaddleView placed on it ten pixels to the right. Ten pixels down. And then the width of this over lay is going to be as we'd expect, ten pick else  sorry, not pixels  points wide and 60 points tall. So what does that mean in real terms? This is why when we start this thing  let me quit this simulator. So if [inaudible] familiar, we can double tap there. Click it how old. Quit paddle. Or you can just click stop. And then you can hit run again to rerun this thing. Notice that it starts in the top lefthand corner. But the projector is kind of  the contrast isn't great. Take my word for it that that paddle is not truly in the top lefthand corner of the iPhone. It's instead ten pixels down, ten pixels over. So in itself is with respect to itself in its own top lefthand corner. But that's just because the image itself was only ten by 60. Now we're painting it on the canvas by offsetting at ten by ten. And why? I just thought it looked marginally prettier to offset it slightly from the edge of the phone. No other reason. All right, so if we now go back into the ViewController.m, what more is happening here? This line of code, addSubview. We've not done this before. But we've kind of felt the results of the line of code like this before. So thus far when we've dragged and dropped things like buttons and text fields and sliders from that little menu and interface builder and dropped it, we've been adding a view on top of another. In other words, adding a sub view. This is the corresponding line of code to dragging and dropping in that interface. I'm taking my paddle and laying it on top of the game board itself. Which is just that big black rectangle by the default. Okay. So now, turns out, making this super simple and kind of pointless game is as simple as implementing the touchesMoved method. So the touchesMoved method is a little different from the pan gesture of recognizer that we implemented earlier. TouchesMoved actually allows you to dissect all sorts of touches on the screen. Multiple fingers, touches on different locations. And it turns out, this actually makes it even easier to respond to those key presses that we could have done this in different ways. So touchesMoved is going to be fired anytime a UI view is touched on the screen. And what's going to happen here is this. When this method, touchesMoved is called, actually the method is called touchesMoved with event. I first ask the event that I've been passed as my second argument, give me all of the touches and then give me any object. This essentially gives me in this case, the only object that could have been touched. If there had been a whole lot of things on top of one another, it's possible that multiple things would have been touched because of the various Z axis, so to speak. But in this case, there's only one paddle on the screen. So I only care to get whatever is in that set. So any object will do. I then  with this line of code  ask it for its location. What are its XY coordinates essentially. And I store those in something called a CGPoint. A CGPoint is just a [inaudible] X comma Y. So where on the screen was that figure touched? Now, what do I want to do? So, I don't care where the user's finger is along the X axis. I only care where its on the Y axis. So I don't care if the user goes up, down over here or goes up, down over here. He or she is is only going to be able to move the paddle along some fixed axis. So which value? Dot X or dot Y is of interest to me here? The location dot Y. So, if I want to center the paddle, notice what I'm doing here, turns out that center is a property associated with the PaddleView or more generally, any UI view has a center. And I need to assign it in X comma Y coordinate. I'm actually not going to bother. I'm actually going to change its Y location. But I'm not going to change its X location. Because I don't want the paddle to start moving along the X axis in this landscape mode. I only want to update the Y axis. What I need to assign its center in X comma Y coordinate. So I have to actually give it a point, a CG point make gives me that [inaudible]. Gives me an XY pair. So, in the end, we get this very simple, kind of pointless game, where the thing follows my mouse or my finger perfectly no matter where on the screen my mouse is without actually responding to the lateral movements. Yes? [ Background Discussion ] Absolutely. We could constrain the touch to only work, for instance, if actually touching the white box. By actually looking at the X coordinate and the Y coordinate and saying, are you within some sort of bounds, if so, move, if not, ignore. Absolutely. And we can kind of change the functionality of this thing altogether if I instead change this line here from the same X that it currently is to Location.x. What's going to happen if I now run this version? Should follow my finger, or in this case, the mouse pointer. If we go to the simulator here. Put this up and  this is kind of a stupider game now. Well, actually, you might have an advantage now, if playing pong. So, all right. So what remains to be implemented? You saw pong a moment ago. And you might've played pong years ago. So, we've got the beginnings of it. We've got the users half of the game. What more do we need to do? Yes? Yes, so we need to implement some kind of little white ball that's going to bounce back and forth. In fact, the bouncing sounds kind of interesting. Because if it hits the top or the bottom, we need to do some kind of reflection, like on a pool table or like from geometry. So we have to think about that. What else has to be implemented? So the tally, we have a big score at the top. So maybe that's a UI label. We can kind of cut some corners and not do everything in graphics. We can actually just use a font and actually update two labels for the left guy's score and the right guy's score. It's collision detection of what? [ Background Discussion ] Yes, exactly. In addition to the top walls from which we want some bouncing to happen, the end walls mean appoint has to be scored. So we have to somehow detect if you've gone too far left or right with the ball. And we have got to detect if if you've hit the left or the right paddle and that ball have made contact. So there's a lot more to think about but these are all probably buildings blocks we can start to piece together. So let me go ahead and open a final form of this and see if we can pluck off piece by piece. And see what the origins of each trick are. So here is, I propose, a working solution. And even I kind of cut a corner here. Based on the files you see here, what corners have I cut thus far? Really just in the interest simplifying things we've already looked at. Yes? Yes, exactly. I have a pong view, which we'll see, kind of manages the whole game. But I don't have a PaddleView anymore or I don't have a ball view because I realized along the way that you know, it'd actually be a lot easier to make a paddle in Photoshop and a ball in Photoshop and just import [inaudible]. And so, I seem to have done exactly that. Paddle dot ping and ball dot ping are are just going to be graphics. But that's enough. I just can't put out pings on the screen. What object  what class do I have to wrap around these images as we saw with Rob before? So a UI image view. So we're just using a different UI image view rather than making absolutely everything from scratch. So, we'll start as always in the app delegates. Nothing going on there. AppDelegate.m, nothing new going on there other than  actually, this is one good thing to highlight. We've used the AppDelegate for terribly little other than the builtin functionality. But what do I seem to be doing with this application will resign active? A bit out of context now, but take a guess. What does this mean and what am I doing in response to it, do you think. [ Background Noise ] How about the first question first. When does this method, applicationWillResignActive likely get invoked? When I what? Close. Just the . Will resign. Go ahead? So, it's not actually orientation, it's instead when the app is background. So if I get a call and I take it or if I push the home but done and I resign active state. Remember when we make key  made the key an active window earlier? This is the same idea. The opposite of that. So, what am I doing? I'm apparently passing a message called kickOff to self.viewController. And I only know this intelligently in hindsight, the first time I sat down to implement something like this, anytime I did get a call or anytime any background to the application then came back to the application, I immediately lost. Because I had no recollection of where the ball was. My brain wasn't quick enough to actually move the  I tell my finger to move the paddle to catch the ball. So then I've realized  wait a minute. If the user has to effectively pause the game to take a call or respond to an SMS, background and whatever, it'd be a nice courtesy to pause the game. So kickOff does effectively that. It just moves the ball back to the kickOff location. The idea being I figured, let's just start from the  let's not reset the score. Let's just reset the ball's location to the middle. Like you might have in a soccer or football game. All right. So that's the only difference there. PongView.h doesn't seem to have much going on here. PongView.m looks like this. Up too much, but a little of this low level stuff. And I thought I'd draw something different. Let me open up the game again. And in the simulator there was one other design element on the screen. Does anybody remember what? [Inaudible] yes, the dash line in the middle. So this is surprisingly non trivial to do. And I didn't want to resort to Photoshop for everything. But I thought that would kind of look like a nice line down the middle. And we can draw this using core graphics on top of my canvas. So in this case, I first need to get something called a context. And the context  you can kind of think of as like the canvas. The current context for your graphics. And now we have some sort of weird use of C. But in the end it's fairly straight forward. I'm first declaring a variable called dashes. That's of what data type? It's sub type CGFloat, but specifically  it's an array of CG floats. Whatever that is. Core graphics float. So it's some representation of floating point values for this particular library. One comma one is essentially as we're going to see, it's going to mean, draw a little bit of white then have blank space. White  blank. White  blank. And that's how we get this sort of zipper affect of the screen. All right so, CGContextSetLineDash. So this function is essentially saying, what's your canvas? Dashes is what pattern do you want to use? And two just means how big was that array? Next line here, CG set stroke color with color  what's your canvas? What color do you want me to draw in? So in this case, this is a bit of a commingling of C and objective C. UIColor's a class. WhiteColor is a convenience method or class method inside of that class that returns to you some of objective C representation of the color white. .CG color converts that NS UIColor object to a C style struct for the core graphics library. Down here we set the line width to be fairly arbitrarily five points wide. We move to the point, 240 comma 0. So we're essentially going to the middle of the screen. If we assume 480 pixel, 480 points total. AddLineToPoint, this is saying, go from where you are all the way up to the top. So sort of draw that dash line. And then lastly, fill in the dots, so paint along the trail you just left. So if you remember like a language like a logo years ago. The little turtle turning up, down, left, right. And drawing things or leaving a trail? It's the same kind of idea that where you move a cursor around and you tell it when to put the marker down and draw. When to let go and so forth. We've essentially drawn a dash line in that way. And now the whole point, was again, to over lay on top of our view, this pong view. So here we have ViewController.h. We're almost into the brains of the game. ViewController.h apparently declares one method called kickOff. Why did I put it in my .h file? I feel like I'm regressing to our previous techniques. Yes? [ Background Discussion ] Exactly. In my ViewController, rather in my AppDelegate.h, recall that I called  AppDelegate.m  recall that I called the kickOff method in this line here. And that's why I imported the ViewController.h. And that's why in ViewController.h, I'm actually declaring this method publicly, so to speak, in the .h file and not in some nameless category in the .m file. All right? So, the nib file looks like this. It's a little different this time. And then I've seem to have laid out in advance, a few different widgets, so to speak. What appears to be on the screen here? So some text. So I con conjecture this is a UI label. That's another UI label and I just put some default text there even though the human never sees it. What else is on this screen? Yes? Yes, so the image views. So let's take a look. If I first expand to the hierarchy here, I can see what I've laid down on this canvas. And indeed, there's three image views or UI image views, the class name. And to labels. And if I actually click on these things, with we can see how they're configured. Let me click on the ball in the middle there. It's ten pixels by ten pixels according to what I made in Photoshop. And it's in data UI image view whose image source has been specified to be that ping in question. Just like we did with Rob [inaudible] earlier. Same deal for the others. And score left and score right, if we go to the identity inspector, is indeed a UI label. So in this case, what I literally did in advance was I dragged and dropped three UI image views from the pallet of options down there. And I configure them, just like I did with Rob earlier to be ball.ping or paddle.ping. So as to lay that out. And then the scores I just manually typed. Previously, they just said label. And they could still say label. I just thought it was a little more instructive to give them left and right names, that's all. All right. So now if we go to ViewController.m, here is where all the interesting stuff must be happening. So first, I decided just to make it easy to tinker with my game, to declare a velocity, constant at the top of the file. Initialized to 10.0 in a floating point value. So this is like the speed, ten pounds per second. And or some unit of time. And then I have inside of my nameless category, a CG point velocity. So, somewhere in this class, I need to keep track of what is my current velocity. Because a velocity recall was essentially a vector telling me how fast to go. Up to  straight up or to the right or the opposite thereof. So it's some kind of speed, a change in rate, DYDX. So I need to store my current one so I know at every second of the game how fast should the ball be moving. Now I have a whole bunch of private properties here. But most of it is expected. Then I've got IB outlets for all three of the UI image views that we saw earlier. And I've got two IB outlets for the UI labels that we dragged and dropped. So that leaves a few here, an NSU integer. What might that mean? Yes, so it's an unsigned integer, why? I figured the score never needs to go negative. So just to be proper, I'm going to specify that it's an unsigned  that is non 0 integer. I could have just done little U, unsigned int. But, just to be consistent with iOS practices, I gave it the NSU integer, which is just the  it's not a class, it's just a type depth, it's a synonym for unsigned int. All right, I've got one for the left and one for the right. And [inaudible] for pause. I needed some variable just to keep track of whether or not the game is paused and when does it seem to pause based on our tinkering earlier. What's that? When it's in the background and also  in the beginning, when the ball is just sitting there in the middle before I actually start interacting with the app or conversely every time there's a score made, then the ball goes back to the center and I have to touch it for the game so resume. All right, so now, in the ViewController, some of this is  a lot of this is now just logic. So, after initializing the object with the nib name, I'm initializing the score left and right to 0. I'm first declaring a velocity. So a velocity has to do with motion. And you can represent it with a point. If a point is just X comma Y, you can just treat the X as delta X and the Y as delta Y. Change in X, change in Y. So I just used them now familiar CG point make velocity comma velocity. And this just means if it's 10.0, what did we say it was earlier, the constant. 10.0  this just means that for every unit of time, move ten points this way, ten points that way, effectively going on a straight diagonal. All right, so what happens next in this initializer? This is how the game actually has motion. So we declared what's called an NS timer. We schedule it with a time interval of .05. So every five hundredth of a second I want something to happen and I just decided on that by trial and error to see what would feel right. Targeting myself with a selector of play. So apparently, I want what method to get called every .05 seconds? The play method, all right? And beyond that  and it repeats, in that, if you recall from Java Script, they're set interval and they're set time out. This is like set interval, given that I'm passing in repeat, a value of yes. So now, what happens next? Nothing seems to happen thereby default, let me scroll down, there's a play method. A lot of math there, touchesMoved. So touchesBegan. So it looks like what I'm doing here is when there's a touch on the screen, I am changing the value of paused to no. So this is my main way of kick starting the game. As soon as touches begin on the screen, doesn't matter where the human touches, that means kick the ball. Let's start the game of pong playing. And I change that [inaudible] field. So presumably, my play method is going to check that value. So let's go into play here. And indeed, if the game is paused, just return immediately. Don't play anything. Don't move any mouse movements or cursor movements or ball or paddle movements otherwise move the ball. So this is very similar behavior to before. Even though this is being called on a timer not in response to user action, what do I want to do every unit of time? I want to move the ball how? Using its velocity. So if its velocity is ten comma ten, every time the clock fires, I want to move it over ten and up ten, if that's its current velocity. And that's what I'm doing. I'm making a new point. Taking the ball's current X location, adding the velocity's X values. Then comma, the ball's current Y location. And adding the velocity's Y value. But now I have to somehow detect when the ball's in the goals as was proposed earlier. So, what is this line of code saying? If self.ball.center.x less than 5, what's the implication of that logic play? [ Background Discussion ] Exactly. So recall that 0 comma 0 is the top lefthand corner. So if the ball goes within five pixels of 0, it's really all the way over to the left at which point, I'm just going to say that's the goal. It went over the boundary. So who should get the score? The guy on the right. So score right should be plus plus. Because he's the one who would have kicked it into that end. And then I called self kickOff. Well, what does kickOff do? Let's come back to this function  this method  in just a moment. KickOff does a few things. It pauses the game, apparently. It then updates the scores based on what's in the NSU integer. So the unsign integers are numbers. But I want to turn them into strings so that I can paint them on the screen in terms of those labels. So that's using some building blocks from a few weeks ago. Now I want to center the ball. And I'm going to go ahead and center this at that particular location here. And then I'm going to go ahead and align the paddles, which is just a bit of trial and error. Figuring out exactly what made sense on the screen. And now if I scroll back to play, what happens otherwise if there's no goal on the left or on the right? Well, bouncing is kind of an interesting thing. So what is this, if condition, handling? The highlighted lines are doing what and how? Yes? [ Background Discussion ] Okay, good. So as the comment says, this has to do with bouncing off the top and bottom, but how? Well, if the Y coordinate of the ball center is less than five, that means it's really close to the top. And if its velocity at that point is some value, how do you make it stop going upward? Well, just change the velocity to the negative. So if we effectively want to make right angles when we hit the side of the wall, it actually suffices. If again, you think of the motion as X component and a Y component, if the ball is going up this way, you don't want to change the X motion. Like, you don't want it to go this way, because that would be weird if the ball hit here and then went this way. You want the ball to go this way and keep going to the right, but you want it to start coming down. So all you have to do is flip the Y from positive to negative or conversely negative to positive. And that's exactly what we're doing inside of this condition. If we get within five pixels of the top of that screen, go ahead and flip the Y's velocity as with that negation there in that line of code. And the [inaudible] is just handling the bottom of the wall as well. And the fact that I'm using a negative sign here means that it doesn't matter if the ball is going up and now would have come down, or if it's going down, now it's going to go up. The left paddle is a little more interesting. And how are we apparently detecting intersection? Well it turns out in the core graphics library, there's a helper function called CGRectIntersectsRect. And you can pass in two rectangles. And it will return true if they're overlapping, which is perfect. And this is why I didn't quite make the ball a circle and decided it'd be easier to just make it a ten by ten square. So this way no matter where it touches, it's sort of geometrically reasonable to assume that it's going to bounce. And so in this case, if the frame intersects  the frame of the ball intersects the frame of the paddle  then, go ahead and inverse the velocity, from negative to positive or positive to negative, depending on which paddle you have just hit. If you're on the left or you're on the right. Yes? [ Background Discussion ] If you increase the velocity of the ball, would you get a problem? Define problem. [ Background Discussion ] Oh, good question. Yes. So, potentially, I have made certain assumptions about the thickness of the ball, the velocity at which the ball is moving and how frequently I'm firing the clock timer. I could absolutely come up with values whereby the ball could be here at one firing of the clock. And then here at one firing in the clock. And the paddle could have been here in the middle. So that would just be a mathematical mistake on my part. And something that could  I'd run the risk of  if I had variable velocities. But all I'm doing with my velocity here is just inverting it, positive or negative. Good question. Other questions you have? All right, so, here is my artificial intelligence, if you recall want to have basic AI in your game. Really, all I have to do is tell the paddle to move toward the ball along that Y axis. And as long as he can move just as quickly as the ball, he will never make a mistake. So what am I doing? So, if the velocity at which I'm moving is negative, what does that actually mean? If the ball is moving left  so that means that it's coming at the computer's paddle. My paddle was on the right for this version. Computer's on the left. So if the ball is moving this way, that's the indicator, according to this code  the computer AI should start doing something. So if the ball's center Y component is lower than the paddle's Y component, the paddle should  per the next line of code  move its center toward the ball. Conversely, if the ball center is higher than the paddle, the paddle should move up toward the ball. And so, no matter what it seems, this paddle will always keep pace with the ball and really only I, the human, am ever at risk of losing. So let's see if this is indeed the case. If I run this version of the game. We now have two paddles on the right. If I click, that's when the kickOff starts. And notice, he only moves when the ball is coming back at him, because of that check. Though we could add some randomness if we really wanted to give the human a fighting chance, we could have the paddle keep moving somewhat randomly. We could change its speed. But for the most part, we have a pretty boring game. But we can make it more interesting if we go back here. And what can make it more interesting? How about we change this to 30 points per unit of time. Now, if we rerun the program, we'll get a game that's a little harder. And come on  now, if I click  damn it. Damn it [chuckles]. [ Chuckles ] There we go. Thank you [chuckles]. Okay. So it's really hard now. I mean, if you can imagine making this into even more of a game, maybe a utility app where it flips over. You can change the size of the paddle, kind of like a game arachnoid years ago, where things get harder or easier depending on the settings. So there's a number of things you can do with this. But at the end of the day, we've really didn't write all that much code, right? We asked iOS to inform us when is the movement happening with the touches? So we could respond to that. Then we drew some things in advance. But we've seen that we could totally skip the Photoshop step and just draw these paddles as their own classes and instantiate them and do something almost identical with the ball. Just making it a little smaller. And at the end of the day, the only thing that I'm doing here is I'm borrowing some code from my paddle example. Anytime the touches move, method is called. And that means something has happened on the glass where the human's touched. I'm going to ask, give me one of those touches. Figure out what its X comma Y is. And move the right hand paddle to that side of the screen. So, really, the human side of things boils down to just those three lines of codes. We have yet another few pieces of buildings blocks there. So any questions on our first two dimensional game? [ Background Discussion ] Good question. Am I doing anything to prevent the paddle from pushing off the screen? Yes, I am in the sense that my code is only ever altering the Y axis of the paddle. I'm only allowing it to move up and down. So notice here, recall this line of code from our previous example. The paddle on the right, his center, is only ever being updated according to the Y axis. So notice, this value here, the X value, this is literally the paddle's current X location. Because it's self.paddleRight.center.x. So, what is your current X location? And the fact that I've pasted that as the first argument to CGPointMake, means whatever your X location is now, it's going to stay that way, because that's the new point that I'm making. But location.y is coming from what? From the human touches based on these two previous lines. So in short, this third and final line of code in here is just ensuring that the paddle's center will absolutely be able to go up and down. But it will never respond to left, right movements. But with we can decouple those. If I go back, just like I did last time, and say, "Go ahead and let the user have location.x," and now run this. Now this game's  I can't do 30 points per second, ten? Now this game gets a little more interesting in that I have a bit of advantage where I can just kind of chase this  oh damn it [chuckles] over there. So that has to do with the refresh rate, so to speak. So now the math a little off in that I can't assume a certain access. But now I have decoupled it from that axis. Oh, it is. I'm just stopping. My mouse can't quite pull it all the up there. But yes, it's going off the screen somewhat. And with he can detect that too, because we know the height of the thing. And we could just ensure that you couldn't go any higher than the glass. In this case, but if you've ever been bored like  what do I usually do on my phone? Sometimes when you're really bored in iOS, you can start using your thumbs and like start pulling down on Safari to see how far [chuckles]. So other people have done this  yes? Okay. So someone has checked for that in Safari, we have not checked for that here. So, in theory, you could get it to go off the screen and probably get it such that you can't, maybe, can't get it back depending on where it's detecting the fingerprints. I'm glad that's normal behavior [chuckles]. All right. Any questions then? All right, so what the lies ahead? Well, evil hang man is still in front of us. On Wednesday, we are going to take a direction in a lab that's not specifically about the final project because there is no one specification. It's up to you guys to propose this. We'll have the specification posted for it on Wednesday. But it'll essentially boil down to  come up with an amazing idea. Propose it to your TF and await his confirmation or request for modification to the idea. And the request won't be, "We don't like your idea," we'll be more, "We don't think that's realistic in two weeks." Or we think "That's too realistic in two weeks." Just to give you a sense of calibration so you can bite off something that you can indeed chew. And what we'll do is try to calibrate you so you have a threshold, a quality threshold, that you'll definitely need. And we'll also try to push you a little bit to have, say, a good, better, best version of your application. Or it'd be amazing if you get the best version. But we'll be quite pleased if you get the good version out the door in time for that app party. So in lab this week, what Chris Gerber will do is introduce you to some more advanced techniques in iOS to further seed your minds with opportunities. Even though the proposal will be due shortly thereafter. Realize that you can change your mind. If you realize, "Wow, I love the accelerometer. I really want to do this instead." Just make sure to have a twoway conversation with your TF to make sure it sounds like a reasonable change. Why don't we officially an adjourn here for tonight and we'll see you next on Wednesday.