字幕列表 影片播放 列印英文字幕 [ Music ] >> Stanford University. >> Alright, so welcome to Stanford CS193p, fall of 2013-14 academic year. This is our very first lecture and we are going to be covering developing applications for iOS, so specifically iOS7. Today's lecture kind of has a first part and a second part. The first part is a little bit of logistics. The second part is I'm going to dive right into the course material because there's a lot to cover and so, we need to start covering it. [Pause] So, what will I learn in this course? I think you know what you're going to learn in this course. You're going to learn how to build cool apps, okay? iOS is a really cool platform for building apps, you probably already know that. The apps look cool, they've got animation. What's really cool is they're in your pockets so you can whip them out and show them to your friends. You don't have to send them to a website or go get a computer. It's also really easy to develop really powerful apps in a really short amount of time, as you're going to find. This course is only 10 weeks long, and while this is Stanford, I know, you're all really, really good programmers and all that, it still, 10 weeks is not a lot of time, so when we get to the end, you're going to see that it's a very leveraged platform for building things. And, you know, the community is quite vibrant, being able to distribute your apps via the app store and not have to put them in a box and put them on a shelf in a store, is really a big, big difference when it comes to marketing a product. Okay? And you'll, you'll see that. The second thing you're going to learn in this course though is real-world application, a lot of the computer science things you're learning in other classes. Okay? So, we're going to be doing networking, we're going to do multithreaded, we're going to be doing all kinds of graphics, we're going to be doing animation, we're going to do object-oriented databases, we're going to do all that stuff for real, okay? You're going to see what it looks like to apply all those computer science concepts, especially how to combine them into a real-world platform, where you're making real apps, okay? And quite a few, many dozens of my former students have shipped their apps on the app store and you may well too. Okay? So this is really, this is a good course to kind of combine or synthesize all of the things you've learned in a lot of your other computer science classes and touch it up against the real world. Okay? The prerequisites for this class are super duper important, okay? This, it's just key to make sure you have these prerequisites and really think long and hard, if you don't, whether you want to give this class ago. CS 106 A&B or, or CS16x are absolutely required, okay? If you don't have that or equivalent, definitely, don't even think about it. The second requirement I've added this quarter, based on experience, is CS107 or CS108, which is great, by the way, if you're taking CS108, you'll really be ready for this class. Or even CS110, and part of the reason I'm requiring these extra classes is just so you're farther along the programming experience curve because this class is a lot of programming, and so for those of you who are used to a lot of programming, you, you're used to it. But for those of you who aren't it's kind of like, whoa, do a lot of programming here. It's going to be a little unbalancing. So, that's why I've required all those. Now if you've done a summer internship of you've done some programming or something like that, that's definitely a substitute for CS107, 108, or 110, right? Or if you've done some other CS class that's even more advanced than these, that's fine too. You've just got to understand that this class is, you know, a programming class, there's a lot of programming. And most importantly, you got to really be comfortable with object-oriented programming. So I put a bunch of terms up here, like message and instance variable and superclass and subclass, if you don't know these terms like the back of your hand, it's going to be hard for you to get this class, because I'm going to be throwing those terms out left, right, and center. iOS7 is completely object-oriented. Okay, the whole structure, the design of the thing, is object-oriented. So, you just got to know that, and if you don't know that, you definitely want to go get that first. Okay? Take CS106a&b equivalent first, and then get a little more programming experience and then you're good to go. Okay? We're going, you're going to be writing apps in this class with dozens of classes that you're going to write by the fifth, sixth week so, you know, if the biggest app you've ever written is got 3, or 4, or 5 classes in it, oh, this is going to be a step up. Okay? The assignments, we've got this weekly assignments for the first six or seven weeks, and then you've got a final project at the end. All of the homework assignments have detailed write-up of the required task and what we're evaluating you on. And they also have hints in there, because I'm not trying to make the homework assignments be really, really hard, and all the homework assignments also directly are re [pause], they're basically reinforcing what has been taught in lecture in that week, they're not a bunch of random new stuff to learn. I'm a big believer in a teaching methodology, which is I'm going to tell you about a concept, via slides, and then I'm going to show you it by demoing it to you, actually writing an application that does, then I'm going to ask you to do it on the homework. So that's three times you're going to see every single thing pretty much in this class. By the end of that, you're going to know how to do it. Okay? And you're going to feel confident and experienced to do it. So the homework is all about that. It's about just doing what you saw me do in class and talk about in class and apply it. Alright. Now I'm going to really briefly go over what's in iOS, I think most of you know what's in iOS, hopefully you've all seen an iOS device or you have one in your pocket, I bet 90 percent of you do in this room, but I'm going to try and summarize it, this is really hard to do because I'm going to try and do it in four minutes or less, or five minutes, and it's so big that, I mean, I could have two lectures where I just talk about all the different things and just summarize them. So, this is going to try and group them into some sort of sensible groups so you have an idea of what's there from a development standpoint, then when we go off and start doing it all then you'll start realizing whoa, and once you learn how to look in the documentation you'll see, oh, look at all that stuff in there, and you'll figure it out. So this is just a high-level overview. So, I, I've used this division into these four, kind of groups. Core OS, which is the stuff that's close to the hardware. Core services, which is an object-oriented on top of that, that kind of makes it so you always are programming an object-oriented layer. Media, because these devices are basically iPods with a phone in them or with a big screen on them, but media is really important to these devices, and then finally Cocoa Touch, which is the UI layer. Okay? Of buttons and all the switches, things like that. So let's talk about what's in each of those layers, kind of, little skimming the surface of what's in those layers. At the Core OS layer, near the hardware, is a Unix kernel. Okay? This is a Unix operating system on this device. And BFD-based mock, and so you get everything you get with Unix. You're getting sockets and you're getting file system, permissions, all that stuff, plus you're getting a bunch of other stuff that's kind of specific to a mobile device like this, like power management, and key chain access to kind of manage the security of things. Bonjour, which is this kind of network, finding other things on the network. So it's got all that stuff, it's a very powerful underlying operating system. But all of that API or most of it is in C, and we want to be programming kind of purely object-oriented layer. So we're going to be mostly operating when we're talking, touching those things at the Core surfaces layer. So this layer has things like language, things that, that kind of make the language more powerful, like arrays and dictionaries, and strings and things like that, plus it has object-oriented ways to access the file system, it has object-oriented ways to find out the GPS location of your device, for example. It has ways to do multithreading. All this stuff what you want to be able to do, but you want to stay in an object-oriented kind of mindset as you're doing them all. There's a huge layer, foundational layer there at Core services for doing that. At the media layer, don't sleep on this layer, really important layer, you've got video here, you've got video editing, you got images, of course, that it can display, it's incredibly powerful audio for doing 3D audio, if you have games, you can make the Thai fighters feel like they're ripping by you and stuff. All that stuff is in here. This is part of, the part of iOS that really I can't cover in a lot of depth. I'm just going to try and let you know that it's there and you're going to dive down depending on what kind of applications, later in your life, you want to build. But there's an enormous amount there. This is a fundamentally, a multimedia device, obviously, and then, Cocoa Touch is where we're going to spend most of our time. This is where you are going to be building buttons and sliders and text fields, talking to each other, and animation happening, things sliding in and out, and, you know, fading out and fading in. If you want to get the, a picture from the camera from the user, you can do that. Things like localization so that you're app can run in many countries in the world and up your sales by doing that. A whole map kit for doing all the 3D maps that you've probably seen in iOS7 and all that stuff is all in there. And, there's even a view in there that's an entire web browser in a little rectangle that you can just plop right into your app. So these are really high-level objects, and we're going to really be diving into this layer, alright? So this is really the primary. And it's called Cocoa Touch because the API in here was originally developed for Mac OS X, and it was called Cocoa, and of course then when they went to iOS, they adapted, and a lot of API is shared between the two platforms, and, in fact, if you develop an iOS app and then you say someday, oh, I want to develop an app for the Mac using Cocoa, it's going to be very similar. Okay? You're going to be really, it's going to look familiar. So Cocoa Touch, obviously, is the touchscreen version of that, of Cocoa. Okay? This technology, Cocoa, has been around a long time, okay? Probably almost 30 years, believe it or not. From even before Apple acquired it to make Mac OS, what is now Mac OS X, and so it's a very mature API, okay? And it's very well thought out, so, especially if you go with the flow of it, it's very easy to build really powerful things. So, that's what's in there. So let's talk about the tools we use as programmers, as developers, to build these apps, okay? And I've divided those into kind of four sections here. One is the tools, the actual programming tools, and what's great, on this platform, is itÕs pretty much a one-tool fits all. Okay? There's this one tool, XCode 5, and everything's in there. You're debugger's in there, all your source code editing, your source code control, the UI building, everything is in this one app. There's a little adjunct there, instruments, which is for things like profiling your app and things like that. Memory usage, those kind of things, but you're really, all was inside XCode 5, which is really nice because, you know, when you're debugging, you're usually editing your code at the same time, back and forth, back and forth, you're going to different apps and all that would be a pain in the neck, and they've really done a good job of arranging the screen space so that it's sharing between all these different tasks that you need to do. So that's the primary tool, XCode 5, you should all, right after this class if you want, go to the Mac App store, not the store on you iOS device, the Mac App Store on your Mac, and download this. It's free, available, came out last Friday, and you can download it, install it, and, you know, start playing around with it. Some of you might have already used XCode, like in CS106, raise your hand if you've used XCode before for anything. Okay, so two-thirds or more, three-quarters of you. So, you're going to be used it. You're just going to start using XCode now to develop for iOS, alright? There's a new language for you to learn, objective C, it's kind of a funny-looking language, okay, its square brackets and colons, no parentheses on message calls, which is kind of weird for people who are coming from Java or C++ or whatever. The arguments are not put in parentheses or whatever, and I'm going to show you all about objective C, I don't expect you to know anything about it coming in, and if you know Java and C++, which you should if you've taken CS106A&B, then objective C is not going to be a big leap for you. It's a little bit different language, it's a little more fast and loose than Java, for example, and it's a little more, kind of simple and elegant, than C++, when it comes to the object-oriented stuff. So, I think you'll like it. It won't. Some of you who are very, you know, correct programming kind of thing, you love Java, might find objective C a little wild west for you, but you'll get over it. Frameworks, obviously, any big system like this groups all of its objects into libraries, essentially. We call them Frameworks in iOS, so there are dozens of frameworks in iOS. The two main ones we're going to look at, at the beginning of the course, are foundation, that's where all that core services stuff is, like arrays and dictionaries and all that. And then UI kit, okay, that's where buttons and sliders and all those things area, so those are the two main ones, but, there's a whole bunch of other ones, like, you see the Core Data written up there, that's the object-oriented database. Okay? So we're going to be doing that. Core Motion, that's the gyro and accelerometer. Map Kit, obviously the maps. And there's dozens more, okay? And we'll cover as many of them as we can, obviously we can't do it all in 10 weeks, but we'll do as much as we can. And then the last part of developing application in this platform is a design strategy called MVC. Now, this is not unique to iOS, other platforms use MVC, Model View Controller, as their fundamental design strategy. So how many people in this room have used MVC on any platform? Okay, so about half, so you'll know what this is. So, I'm actually going to go over MVC for those of you who haven't and I'll go through it pretty quickly, because it looks like most of you, half of you have done it, and [pause] the main thing to see in MVC here, for those of you who already know what it is, is to see how I talk about it so that when we get into iOS and I start saying things like your model is UI independent, you'll know what I'm talking about and we'll all be on the same page. So this is mostly kind of getting us all on the same page terminology-wise. So MVC, Model View Controller, is essentially a strategy for how to organize all the classes in your application. And what we do fundamentally is we divide all the classes into one of three camps. The model camp, the controller camp, or the view camp, and what, how you decide what goes in each of these camps, well, the model is essentially the what of your program. What is your program? So, as we're doing this MVC talk, I'm going to talk about our first application we're going to build which is a card matching game. Okay? So we're going to build this game, it's gotta bunch of cards on the screen, like playing cards, you know, Ace of Clubs and all that, and you're going to be able to go choose the cards and you'll get certain points if the match. Like the suit matches or the rank matches, or whatever, you get more points, less points whatever, but you're doing that. In that kind of application, a little card matching game, the cards and the deck, and even the logic for how the game is played are all UI independent and in the model. Okay? So how the cards get drawn on screen is the job of the controller. So the controller is, it's job to figure out how am I going, you know, take this set of cards and display them on screen, and then animate their movement and things like that. Okay? That's up to the controller. So the controller controls how the model is presented on screen, and the view, the minions, the classes that the controller is going to use, kind of like the building blocks, the Lincoln Logs, I don't know maybe that's before all your time, but, you know, the things we're going to do build our UI we're going to use in the view, so, the stuff that's in the view is pretty generic. Generic UI elements, the stuff in the controller is very specific to how your UI works, and the stuff in the model is completely independent of how you're UI works. Okay? So, doing MVC is about knowing where things go, but also about how to communicate between these three camps and so I'm going to try and summarize how the communication works between these camps and I've used road markings, you see the double yellow line and then the dashed white line, so that's like you're driving in your car, try to use them as that I have an image for how this communication happens, where it's allowed, where it's not allowed. Okay? So let's talk about the controller talking to the model. Okay? Going from that side of the road over to the model side is a dashed white line, in other words, you can head right across there, you probably want to look before you go, but you can go right across, okay? The controller has to know everything about the model and it has to have complete ability to talk to the model, use its public API as much as it wants, because the controller's job is to present the model to the user using its view as its minions, so it has to have this access. So that's full, unrestricted access the controller has talking to the model. This is a one-way era, or one-way arrow, from the controller to the model. And similarly from the controller to the view, is also unlimited communication because the controller is responsible for talking, using, it's own minions, the view is the controllers' minions to lay out the user interface and all that stuff, so the controller can do anything it wants, I've put that little green word outlet up there because when we have a property of a controller that points into the view, we call it an outlet. Okay? And you're going to see that in the demo on Wednesday, I'm going to say oh, let's create an outlet from our controller to our view so our controller can talk to its view. Alright? What about this communication? Model to view, never, and why is that? 100 percent obvious. The model is completely UI independent. So there's absolutely no way it could talk to a view or object or anyone in that camp. Because the view objects are fundamentally UI objects, they're kind of generic, but they're still fundamentally UI objects. Similarly, since the view objects are kind of generic, they can't be talking to any specific model. They need a controller to interpret a model for them. Okay? So there's never any communication this way, that's why it's a double yellow line, that's why these lines are red, that's why there's fire, okay? Never go across that line, ever. [Pause] What about the view talking back to the controller? You got these generic view objects, like buttons, can they talk to the controller? Well...yes, they can, but they have to be careful because the view objects are generic, so they can't really know much about the control, so, they can only communicate back to the controller in a blind way, where they don't know the class of the thing they're talking to, and, in a structured way, a way where we all agree, we're going to communicate this way, between the view and the controller, so what's an example of a structured way? Well one is called target action. So the controller basically drops a target on itself and then it hands out an action, which is like an arrow, to the view and says to the view, okay, when you do what you do, like you're a button and someone touches you or you're a slider and someone moves you, send me that action. Okay? So in this way, the generic button, or slider, is communicating back to the controller, it has no idea that it's a card game controller or a space game controller, it doesn't know what kind of controller it is, all it knows is that when something happens in itself, boom, it sends messages to targets. So that's a blind, simple, structured way for the view to communicate with the controller, okay? But what about more complicated ways? Sometimes the view, things are happening in the view that are somewhat complicated and the controller needs to be informed of what's going on, synchronizing what's happening. And one way to think about this is these words I put here, will, should, and did, when the view is kind of like [pause], let's say on the scroll view and I'm scrolling around, and I want to let the, the controller, somebody, know that the user just did scroll. Okay? Or the user puts down the touch and is about to scroll, I want to let the controller know the user will be scrolling. Okay? Or the user puts a touch down and the scroll view wants to know, should I allow the user to scroll here, is that allowed? All those things, the scroll view itself might not have enough logic to know the answer to those questions, so what it does is it delegates the authority to answer those questions to some other object. Now it doesn't know the class of that object, all it knows is that other object can answer these questions, will, should, did, this, that or the other thing, like, should allow scrolling, did scroll to point, things like that. So those are the kind of methods you're going to see in these delegate protocols. Now I know that CS106A&B do not teach protocols, the word proto, how many people know what the word protocol means in object-oriented programming? See, very few of you, so I will be teaching that. A protocol is just a blind way to talk to another object. You're, you're going, when I teach you, you're going to be like, oh yeah, I know what that is, we didn't really call it protocol, or whatever. But, that's how we do delegation, okay, this blind communication. Also, another important thing is that views should not own the data that they're displaying. They should not own it. In other words, it shouldn't be a property inside of them where that's the truth of that data. And the easiest example for this is all the songs in your iPhone, on your phone or your iPad, right? You might have 10,000 songs in there. So if you have some kind of generic list view in your view, you can't transfer all 10,000 songs to its instance variables and expect it to hold 10,000 songs so it can list through it. A, that would be inefficient, and B, that information, those 10,000 songs belongs where? In the model, okay? Because you're song database is a model. It has nothing to do with UI's, just a list of songs and artists and albums and all that, it's in the model. Some controller has to look at that database and tell a view how to display all those songs, okay? So, we need that communication to happen here and the view is displaying some sort of list, and you're touching down and you're flicking on the list and trying to see more songs, how does that communication happen, and the answer is, we have another special kind of delegate, which we call a data source. Now the data source doesn't do the will, did, should, it's going to be asking questions like count, like how many songs are there? And the controller looks in the model, 10,000. Response to the view, there's 10,000. The view makes space, internally, for 10,000 things, it doesn't know what they are, moves the scroll bar indicator a little bit, so that you know where it is, and then you start scrolling, flipping through it, and its start sending the message to the controller, give me the data at [pause] line 150, next 10 items. See what I mean? And then you flick down some more, now it's saying 250, 10 more items, and so the controller is going back to the model and saying give me more, give me more data, and it's providing it to the view in this blind way. So see how the view is getting data from the model through the controller, in this kind of blind structured way. Okay? That makes sense to everybody? So data source is just a kind of delegate, it's a specific kind of delegate for getting data. So you're going to see that there are classes in iOS that have a data source, and they usually also have a delegate. Most sophisticated classes in iOS have a delegate, the will, did, should kind of things. Some of them have a data source, it depends on whether they're showing a lot of data or not. Now simple data, like if I had a view, if I invented a view for my card game called playing card view, and it just has a suit and a rank, okay, we're not going to do count data at for just suit and rank, we are going to set those properties. And so the view then would have those, that data set in it, but it wouldn't be owning it, right? The model would still be owning the suit and rank, the view is just getting that data to present it. Okay? So simple data we might transfer to the view, but it's merely for it to display it. Okay. This all adds up to the controller's job being to interpret and format the model data for the view. That's the controller's job. And when we do our demo, I'm going to be marking like, oh, see, I'm writing this code, this makes the controller perform its job, which is to take the model data and put it in, and using it to view minions, put it on screen, okay? That's what the controller does. What about this communication? Can the model talk to the controller? Again, obviously that's verboten because model knows nothing about UI, so it couldn't possibly talk to a UI object like the controller. But sometimes things change in the model and the controller needs to know about it. Okay, data changes, a database changes or the model is some network database and somebody changes something on the network and it changes, and the controller needs to find out. So, how do we do that communication? We do that using kind of a radio station model. Okay? So the model, a radio station concept, the model will use this concept to essentially broadcast information to anyone who's interested, okay? And the mechanisms for doing this in iOS are called notification and key value observing, KVO we call it, and so the model can just say, oh, anytime something changes in my model, I'm just going to broadcast on my radio station and then the controller simply tunes into that radio station. And it can find out things are changing. And when it finds out something changes, it's going to communicate via its green arrow to the model, and say, okay, give me that data that changed. Alright? Does that make sense? So towards the end of the quarter, we'll start seeing a little how to do notification to find out, for example, if the data in the database changes. We'll get a notification, the UI can then, you know, the controller can then go talk to the model to get the info. Okay? [Pause] Some people have asked, can a view tune into the radio station? They probably could, but you probably wouldn't want to do that. That would probably be a violation of MVC. Alright, so, we do this, we have all this nice communication and all these rules, and we can imagine building something simple using this, but what if we want to build a big, complicated app? An app that has multiple screens on our iPhone or on an iPad it's got, you know, three or four different areas on screen where things are happening, how do we do that? Well, we're essentially going to combine multiple MVC's, okay? Because you, an MVC can use, as part of its view, another MVC. Okay? So, an MVC, an entire MVC, can be one of the minions of some bigger MVC. Okay? And by doing that and cascading it down, we can build more and more complicated applications. So, an example of this is you might have your calendar app, and it's showing you the entire year, and you click on a month, and now it shows you a month view. Well a month view looks a lot different than a year view. Month view just has all the days and maybe some circle that tells you where you have an appointment on a day, and then when you click on a day, and now you get a day view. Okay? And the day is showing you the hours and what all your appointments are, and you click on an appointment, and now you get an appointment view and it's showing the detail of where you're going and when it is etc. Okay? Well each of those views, the year view, the month view, the day view, and the appointment view are their own MVC's. Okay? But you can see how the last three, okay, are used as, essentially, a minion of the top-level view, the year view, to show more detail. Okay? So the year view, you click on a month, it's going to use the month view MVC to show more detail, so it's part of its view, okay? So, you see this also in iOS with tab bar controllers, right? You have the tab bar, along the bottom, I have four or five things you can choose, well there's some MVC at the top who has four pointers to four minions, which are the four MVC's that are each going to appear in a tab bar, okay? We'll be doing that, for example, in assignment number two or three, where we'll be making a tab bar and you're going to have to do multiple MVC's. Okay? So, that basically results in a picture that looks kind of like this. Alright? Where you got this MVC and you see the purple one that's like underneath the word together there, and it points to three other MVC's outside of its view thing, okay? That's how we're going to build this, that might be a tab bar controller and those might be the three tabs. Okay, and each one is its own little MVC, completely independent, operates on its own, doesn't even know it's a generic, reusable view like thing at this point, it doesn't even know that it's in a tab bar. Okay? It just knows that it's supposed to do whatever it does. And so it's modular in that way. You can also see that there's no communication between any other, there's no other arrows, except for some of the models. You see some of the models are communicating with each other, you know, a big application might have single, shared model. Or, you know, the models might be split off into pieces to be used by sub MVC's, okay? But that's the only kind of communication you're going to have there, all other communication is either the structured communication we saw in the MVC or it's using MVC's as part of the view of another MVC. Any question about that? So we definitely don't want to be having designs that look like this, okay? Where everybody's talking to everybody, we can't tell who's talking to what, it's just impossible to debug a program like this and it doesn't scale. You can't build really big programs this way, it just becomes impossible to know how touching anything would break everything, right? So we're definitely not going to be doing that. Okay? Okay, so that's MVC. No questions about that? Alright. Onto objective-C. So, objective C is a strict superset of C, so everything you can do and see, you can do in objective-C. Okay? And we'll do a lot of C things in this class. We'll do a lot of object-oriented stuff too, but we're going to do a lot of C things, as well. But, there's obviously a few things that you want to think differently about because you have object-oriented stuff added onto a language, and we're going to talk about one of them today, in addition to showing you a little bit of the syntax, we're going to talk about one of these different, think differently things about objective-C that's different than C++ or Java, which is properties. Okay? And I'm not going to read through all of this, I'm just going to show it to you, but properties are basically how we access our instance variable, right? Everybody knows what I mean by, raise your hand if you know what I mean by instance variable? Okay good. So pretty much everybody. So, we want to access the instance data of our objects. And, normally, in Java or in C++, you just, you know, have some syntax to access them and you just access them. In objective-C we don't do that. In objective-C, we have what's called a property, and a property is basically a setter get method and a getter method. And that's how all access to the instance variable goes, through a setter method to set the value and a getter method to get it. And some people who maybe are kind of [pause] performance junkies might say, oh my gosh, every instance variable I have to call a method to set it or get it? But, remember, you're building for a user interface system here, when the user touches down, that's taking million, a million code, you know, you're executing a million instructions there in that amount of time. So, having a few extra setters and getters is completely irrelevant, right? So it's the old [inaudible] thing, right? You don't want to optimize things that don't need to be optimized, okay? You want to optimize the things that are taking a lot of time and accessing instance variable turns out not to be taking a lot of your time, so, let's look at what it looks like, don't get freaked out here by seeing this syntax. It's all new, so, it's going to take some getting used to. In objective-C, every class we have and the class I'm going to show you today is a, is in our, essentially our model that we're going to build for our card game matching app. We're going to have a card and a deck, and we're also going to have a subclass of card called playing card and a subclass of deck called playing card deck. Those are the four classes that are going to be in our model, to start. And, so, I'm going to show you, in today's lecture I'm just going to show you card, only card, and then on Wednesday I'll show you deck and playing card deck and playing card. So, every class in objective-C, you have a header file, card.h, and you have an implementation file, card.m. Okay, this is just like in C++ you might have that h and dot c, or whatever, this is dot m, m I guess is for implementation, I don't know. But it's m [laughter], and so you have these separate things, the difference here is card.h is the public API. That's what your dot h is. It's your public API. Card.m is your private API and all your implementation, okay? Don't get confused about dot h and dot m. All dot h is your public API, that's all it is. It's what methods in your class you want to make public so that other people can call them, okay? So, let's see what the syntax looks like. In your public API, you must say who your superclass is. Okay? You are not allowed to make your superclass be a secret, okay? It has to be public so we have to put it in the header file, and you can see the syntax we use is at sign interface, the name of our class, which should always match the name of the file, by the way, card.h should always have the interface for the class card. And then a colon and then your superclass. Now the superclass of the card class is NSObject. NSObject is in the foundation framework and it's pretty much the root class of every single class in all of iOS, including all the classes you write. Okay? It's this kind of basic class, we'll talk about it when we talk about foundation, but it's going to be the superclass eventually of every single class. Right? Everything, eventually, inherits from NSObject. Now, on the implementation side, it looks very similar, but instead of saying at sign interface, you say at sign implementation and the name of the class. And here you don't specify your superclass, okay? Because you're only allowed to specify that once, and its public, so it goes in your header file. Notice that the bottom of both of these, little at sign end, do you see that? Okay, that just means that's the end of the interface or of the implantation. Okay? So all of your public API goes inside this at sign interface block, at sign interface, and all of your implementation, your private implementation goes in the at sign implementation part. Now, if you import, if you have specified your superclass here, you have to import it. Okay? Which is like pound sign, include. It's a little more powerful than pound sign, include, in fact, it's a lot more powerful, as I'll talk about in a second here. >> But you must import it, otherwise the objective-C compiler won't know what that superclass is, so you have to, obviously, import your superclass. However, we don't usually, when our superclass is something that's in iOS, we don't usually import just that classes header file, which in this case is foundation, we actually import the entire framework. Okay? Now you might say, oh, that's inefficient. [Pause] A huge framework, but of course this is all precompiled and optimized. And, in fact, in iOS7, the syntax for this is really to say at sign import foundation. That means I'm going to use all the public classes in the foundation framework. iOS7 still supports the old important foundation slash foundation.h so you can use that if you want. Now on our implementation file, we have to import our header file, obviously. Okay? Because our implementation file needs to know what we're committing to publicly, in terms of our API, so we have to import that. Makes perfect sense. We can also have private declarations, okay? Declarations of properties and methods that are private inside of our implementation file by putting this little at sign interface, name of our class, open parentheses, closed parentheses. Okay? And then at sign end. So we can have a little space here where we can little private declarations. Now, objective-C does not require you to declare something before you use it in a file, you know what I mean by that? And there's a lot, a lot of languages, you have to declare a method before you can call it, right? But you can do it out of order in objective-C, you can implement a method here that calls, you can implement method A, calls method B, and then method B is implemented down here later in the file. Okay? So you don't have to declare method B first, then implement method A, and then implement method B. So, this little private at sign interface we're mostly going to use for properties. Okay? Because when we declare a property, as you'll see, that setter and getter get written for us. So let's see what that looks like to declare a property. So here's a simple property. It's called contents. So this is the content of the card. This is what's on the card. So this might be ace of clubs. Okay? And because this is your first day, we're going to make the contents be very simple, just a string. Okay? So these cards, they can be like a flashcard, maybe, for learning a foreign language, maybe this is the, the contents are the word that you're trying to learn and maybe it's a flashcard of images where this content is the name of some image and it's up to UI to display an image that matches it. Or in the case of our playing cards, we're going to have this be like, literally the character A and then the character clubs, because there's Unicode character clubs, so the A clubs, that would be the content. So this is the content of the card, what's on the card. And you can see that it's an NSString star. You see at sign property is how we're going to declare that we need storage, per instance of card, in other words every card has its own contents, and it's going to be a string, and so we say property NSString star, now, it's important to understand that in objective-C all objects, all of them, live in the heap and we have pointers to them. Okay? There's no such thing as making an object on the stack or anything like that, okay? They're all in the heap. Everyone knows what the heap is? Any questions about that? That's just where you allocate free memory. So all objects are there. What's' really cool about objective-C is, objective-C will manage all that storage for you. It will allocate for you and free it for you. Okay? Now how does it know when to free it? And the answer is this strong thing, you see the word strong there? If, your properties can either be strong, like this one, or weak, two things, strong or weak. Okay? And all pointer properties have to be strong or weak because the objective-C has to know what to do with the memory and the heap. Strong means keep the memory for this, for the thing this points to, in the heap, as long as I or anyone else has a strong pointer to it. Okay? So, this is called reference counting, it's not garbage collection, its reference counting. So we're going to, the objective-C is going to keep track of every single strong pointer to an object in the heap and as long as at least one strong pointer exists, it's going to keep that thing in heap. As soon as there are no strong pointers left, it will free the memory out of the heap, instantly. Not garbage collected later. But actually instantly, reclaim that memory. Okay? So this is probably new to you, you're probably used to like garbage collection in Java, for example, or explicit memory management in other languages. This is called automatic reference counting and it's awesome. It's really very predictable, this is much better than garbage collection, because, you know, the garbage collector can come along later and do, wreak havoc on the performance of your application as it goes and collects things from the heap. This is very predictable, you know exactly when things are going to be released, it's when there's no strong pointers left to it. What would it mean if this was weak? Okay, if you have a weak pointer, that tells objective-C, okay, I have a pointer to this thing in the heap and keep it in memory as long as someone else has a strong pointer to it. But as soon as no one else has a strong pointer to that thing, it gets freed from memory and this pointer, if it was weak, gets set to nil. Nil means this pointer doesn't point to anything, okay? Nil is the same as zero. Okay? In other languages, you're probably afraid of nil pointers. Okay? Because you do reference a nil pointer, it crashes your program, right? In objective-C, you can send messages to nil pointers even and it will not crash your program. In fact, if you send a message to a nil program, to a nil pointer, it will not execute any code, obviously, because there's no instance there. And it will return zero from, if that message had a return value, it'll return zero. So you have to be a little careful of messages that return structs, okay, but as long as it returns a primitive type or a pointer, it'll just return zero. So, this is going to take getting used to. The fact that we are going to program knowing that we can send messages to nil, to pointers that are nil and that that's good. We'll actually make our code work nicely and we'll use that to our advantage. And that is definitely going to be a change for you who are used to if pointers not nil, then send message all the time, right? Protecting against crashes, you don't do that in objective-C, you just don't code it that way. Okay? So, this pointer could have the value nil, n-i-l, which means it doesn't point to anything. Alright? So if you have a strong pointer and it points to something and then you set it to nil, now that strong pointer doesn't point to that thing, as long as no one else points to it, you can clean up that memory, objective-C will clean the memory up for you. Or if you have a pointer that points to something in the heap, then you make it point to something else in the heap, then you no longer have a strong pointer to that other thing in the heap and as long as no one does, it'll get cleaned up. Okay? And remember weak not only cleans it up, but it sets your pointer to nil, because you only wanted a weak pointer, you only wanted it to point to that thing as long as someone else does. Okay? So that's the strong versus weak. The other thing we're going to put in this little parentheses is nonatomic, okay? Nonatomic means calling this setter and getter that go along with this property is not thread safe. Okay, so you can't have two threads trying to set this property at the same time. Why do we say nonatomic here, why do we want this to not be thread safe? Because the way we do multithreading in iOS is not by having a single object that multiple threads are setting on, we usually have a separate set of objects that are running in another thread, like your model, and then other, than your UI stuff is running in the UI thread and they're talking thread to thread. Okay? So we don't need this and not only that, what's going to happen here when we do this at sign property is objective-C is going to create that getter and setter methods that I told you about to set these contents automatically for us, and we want them to be simple, okay? This is what they're going to look like. We want them to be simple. If we don't say nonatomic, there's going to be all kinds of locking code in there, right? If you have multiple threads and you're allowing multiple threads to access the setter and getter here, then you need locking code, and we don't want locking code, especially if we're going to implement the setter and getter ourselves, which we're going to, sometimes. Okay? But the default here is that we don't implement this setter and getter, it's automatically in there forest. So you can see there's three parts to this. There's the at sign synthesize, you see that? That's basically just saying underbar contents is the name of the instance variable in which the property contents is going to be stored. Now we could say at sign synthesize contents equals foo [phonetic], and then contents property would be stored in an instance variable called foo. But that would be very confusing, so we always use underbar name of the property. Okay? And so that's part one, just basically allocating an instance variable to store this contents property. Then there's the getter, that's NSString contents, return contents, so the dash, parentheses, NSString contents is a method declaration in objective-C, the dash means this is a method, parentheses NSString star means this is a method that returns a pointer to a string, and contents is the name of the method. Okay? So the name of the method of the getter is the same as the name of the property. Then, the implementation is just return that instance variable that we synthesized. Okay? And similarly, the next method is a method in objective-C for setting it. And, again, dash [inaudible] method. Parentheses void means this method does not return anything. Okay? That's what parentheses void means. Then set contents colon, that's the name of this method, set contents colon. Parentheses NSString star is the argument to this method. Contents is just the name of the argument, the local name of the variable in the local contents, context, and the implementation is just underbar contents, our instance variable equals that argument. Okay? So, before I move on, does everyone understand how these two methods are allowing you to set and get an NSString storage space inside your card? Everyone understand that? Question? [Inaudible background question] Okay, so the synthesize line, again, is just specifying the name of the instance variable that we're going to use to store this stuff in, underbar contents. It's kind of weird, you could maybe, it might be better saying at sign synthesize contents to use instance variable with name, underbar contents. That equals, I know, is a little weird. It sounds like it's assigning something, but it's just, that's what, think about equals as, you know, we'll use the instance variable with the name, underbar contents. So that's what the synthesize is doing. If you don't put the synthesize, it's not going to create the space in your card instance, and it won't, there won't be any name for it so you can't refer to it in your getter and setter, okay? Everyone understand this? Any other questions? Okay, now, the thing about it is, when you type the at sign property on the left, this gets added to your at sign implementation; however, you will not see it there. [Pause] Okay? So it's there, but you don't see it. Okay, objective-C is, made it for you, but it doesn't show it to you, but it's there, okay, that setter method and that setter-getter method are there. Okay? They exist. And not only that, they're public, because you put that at sign property declaration in your header file. Everyone got that? So let's look at another couple properties just to see the syntax a little more. So here's two properties that are bullions [phonetic]. Okay? There's no bullion primitive in C, so objective-C has to find, typedef all caps BULL, probably a short or something or an int or a char, I don't know what, but you can think of it as a primitive type, it's a boolean, it's value can either be yes, which is some non-zero value, or no which is zero. And these properties don't need the strong or weak. Do you understand why that is? Because they're primitive types, they're not stored in the heap, okay? They're just a int or a float, so there's no memory to manage so you don't need to know about strong and weak pointers, there's no pointers involved here, this is just a BULL, a bullion. So there's no strong or weak, but we still have the nonatomic, because we still want the setter and the getter to be simple, not having any locking code or any of that business. So we're always going to have nonatomic on every property in this class. We will not have a single property in this entire class that is not nonatomic. So just put it in there, I wish it were the default. Okay? So that's what we're going to do. You can see we've synthesized them both and we've got the setter and the getter for them both, and this is all being done for us by objective-C. Now, one thing that's kind of cool is we may not like the name of this getter, because we want our code to read something like if card is chosen, then do something. If card is matched, then do something. So we really want the getter called is chosen, not just chosen. You know, if card chosen, not as nice as if card is chosen. So it's actually possible to rename the getter by saying getter equals the new name you want. Okay? And that's essentially renamed it, same thing, we'll do the same thing with this one. Getter equals is matched, now that getter is called is matched. And I bring this up because you're going to see how iOS does this with bullion properties, it tends to rename them to is this or has this, depending on what the verb there is. Okay? And again, objective-C is writing all this code on, in the implementation, but you don't see it. But it's there. Okay? Now, [pause] we're going to talk about why properties are good and why it's better than just accessing instance variables directly, [pause] in later lectures, but the bottom-line is it's good for doing things like balance checking, it's good for doing things like when you set a property and you want to updated the UI. It's doing good for things for initializing pointers. Like that end string star contents property is going to start off nil. All properties, in objective-C, all of them, start off zero. So for pointer, that's nil. Okay? So that contents property, when we create a new card, it's going to not point to any contents. That cards going to be blank, okay, it's not going to have anything on it. So, it's nice to use the setter and getter, we implement our own setter and getter that will check to see if it's nil, and if it's not, and sometimes, not with contents, but with some properties, if it's nil, we'll create something in memory. Okay? So that's another reason you use it. So you'll see all these reasons why we want properties in the next lecture basically. Alright, so now, let's look at a method. Okay? Just a regular, old method. You've seen some methods, the setter and getter methods, but what if we wanted to find our own method, our own public method, so I'm going to define this method called match. Remember that I'm building a model here for a card matching game, where I'm going to put all these cards on the screen and the user is going to try and match them. Pick ones that match, alright? So I need a match method. A method that tells me whether two cards match. Okay? So, I'm trying to make this simple, so I've made a simple match method that has the following semantics. It takes another card as the argument, and it returns it an integer. That integer is zero if the cards don't match, otherwise, it's an integer that is higher, the better a match it is. Okay? So like a really good match might be a thousand, but a not so good match might only be a hundred, and, or, or it could be one. Now, the semantics of what that number is, totally depends on the cards, because we're only going to match cards against other cards, alright? And we're going to find out how good a match they are by how that, whatever that card class is, and we're going to make a subclass of this class, called playing card, that's going to give more points for matching the rank, okay, than it is for matching the suit. Okay? But that's up to subclasses of cards to determine what the point system is, okay? So, for our implementation of match, okay, we're going to do a really simple implementation, so, first let's assume that they don't match. Okay, so I just made this local variable int score equals zero, you can see that you can assign a variable, actually all local variables also start out zero, so I don't even really need that equals zero, but I'm a big believer in putting that in if that's really, you know, what you intend, and in this case I intend the score to be actually zero. The score of this match until I go and see if these cards match, right? So it's just a kind of programming style thing here. So, how I'm going to tell, how am I going to tell if this card that's been passed in match, matches the card that it's being sent to? And the answer is I'm going to send some messages, okay? You see the open square brackets notation there, that's the first time you're seeing me send a message in objective-C, and I'm also sending two other messages in this one line. Card.contents and self.contents, you see both of those, those are message sends, as well. So there's two different syntaxes here for sending a message. One is open square brackets, okay, and we'll talk about that one in a second. And another one is dot notation, card.contents. When do we use them? We only use the dot notation for properties. That's how we call the setter and getter of properties, using dot notation. Okay? Now, here we're calling the getter, card.contents is calling the getter of the contents property on the card instance. Okay? How do we call the setter? Exactly the same. Card.contents, but we put it on the left-hand side of the equals. Card.contents equals, now we're calling the setter for contents. You see? So here we're calling the getter. We're also calling the getter for contents on self, on our self. So, in other language this might be called this, right, but you know what self is, right, self is this instance that this code is operating on. So, we are going to compare these two strings, card.contents and self.contents to see if they are equal and we are going to do that with the NSString method is equal to string colon. So [inaudible] equal to string colon can only be sent to a string [pause], so is equal to string can only be sent to a string and card.contents is a getter method that returns a NSString, so we're good to go, right? We're sending is equal string to a string, and the NS equal to string takes as an argument, an NSString and, again, self.contents is a getter method that returns NSString; therefore, we have satisfied all the requirements of this equal to string and we put square brackets around it, and it's going to return a bullion is equal to string is defined to return a bullion whether the contents of those two strings are the same. Notice we did not say equals equals. Okay, we did not say card.contents equals equals self.contents. Because we'd just be impairing the pointers then, not what the pointers point to, okay? Everyone understand why we didn't use equals equals to see if those two strings are the same? So if those strings are the same, I'm going to give one point, okay? So this is either the dirt simple implementation of match, which is if the cards are exactly the same, their contents are exactly the same, I'll get one point, otherwise I get zero. Okay? Now we're going to do much better implementation in match when we do playing card, but this is our kind of dirt simple one. Now, to give you just a little more about objective-C, what if we changed this method, oh, so, yeah, here's a little bit about who's the sender and who's the receiver here. You can look at this in the slides later. Okay? But I'm going to make this a little more complicated. I'm going to make the argument to match be an array of cards. Okay? So now I'm matching this card that I'm sending this to, to a whole bunch of other cards. So now I'm going to need some new algorithm to match, right? So, again, a playing card match, if let's say you had matching three cards, you might give a lot of points if all three cards are the same rank, they're all jacks, you get a lot of points. If only two of them are jacks and the other one is something else, well you don't get very many points at all. If they're all through the same suit, you kind of get a medium amount of points, you see what I mean? So, here I'm changing match to take an array as the argument instead of just a single card. And how would I change my implementation to deal with that? Well, I'm just going to put a four-loop around my if and iterate through all the cards and so this implementation, hopefully those of you who are quick thinkers, you can know what this does, this gives you one point if the card that's receiving this matches any of the cards in the array. Any, not all, any. Okay? Now you can imagine a lot better algorithms here. Maybe you get one point for every card you match in the array or you get two points for one match and four points for two and eight points for three, you know, some sort of binary thing, exponential point, whatever, this is first day of lecture, we're just going to give one point if it matches any, okay? But mostly what I wanted to show you here is what it looks like to have an array as the argument instead of a single card. So that you understand that the argument, what the argument to the method is and also so I can show you the four-loop there. You see that four n [phonetic], a lot of languages have that these days. That just basically means it's a four-loop where it's going to go through every object in that NS array and assign it to card, card is the iteration variable, and execute that if once for each of the cards in the array. Everyone understand that? If you have a question about that, ask? No? Yeah? [Inaudible background comment] Oh, okay. That's a great question. So the question is if I just have that four-line, but I said four card card, not four card star card, in other cards, okay? We'd get a syntax error. Why? Because all objects are always pointed to so we always have that star. Okay? Always. Alright? You can't have a card not being a pointer to it, so the, you know, objective-C would give you a syntax error there, it's impossible to not have that star. Whenever you have the name of the class, it's always going to have that star. Question? [Inaudible background comment] Yes. The question is, another great one, can I use the square brackets to call the setter and getter instead of using that dot notation? And that's a really insightful question and the answer is absolutely you can, it's perfectly legal, because that setter and getter are completely normal methods. There's nothing special about them whatsoever. Okay? That dot notation is a nicety, syntactic sugar only. The question is should you use square brackets for setter and getter, and I think it's a matter of style. You would definitely would want to be 100 percent consistent, you would never want to mix them. And I think most people, most people would say use the dot notation. It makes it clearer, it's a little simpler, nicer, but, you know, you could. In this class, please use the dot notation just so I know you know how to use dot notation. Question? [Inaudible background comment] Okay, awesome question again. Gosh, you guys are so good. Can I use dot notation for a method that takes no arguments, but is not a getter or a setter? And the answer is objective-C will warn you about that, not give you an error, but warn you, and you should never do that in this class. Okay? That is really not that good form, whereas his question was kind of like you can argue, that one, don't do it. Okay? So. Use dot notations only for setters and getters. Other questions? Yeah? >> How do you use a setter with dot notations? >> So, yeah, question is how do you use a setter with dot notation? And it's exactly the same as a getter, it's just that you're using it on the left-hand side of an equals. So card.contents equals, you know, A of clubs, that would call the setter of contents, whereas, you know, this is calling the getter, because it's not on the left-hand side of the equal. Okay? Excellent! That's all I had today, so on Wednesday, we will do deck and playing card and playing card and I'm going to dive right into a big old demo of XCode 5 and show you how all this stuff is actually done, and then next week we'll do, yet more objective-C. Thank you very much! >> For more, please visit us at stanford.edu.
A2 初級 美國腔 斯坦福大學開發iOS 7應用。第1講 班級後勤,iOS概述。 (Stanford University Developing iOS 7 Apps: Lecture 1 Class Logistics, Overview of iOS,) 72 7 weber8246 發佈於 2021 年 01 月 14 日 更多分享 分享 收藏 回報 影片單字