WWDC2001 Session 122
Transcript
Kind: captions Language: en well good afternoon okay so this is the using cocoa Talk my name is a loser I'm the manager of the cocoa frameworks group okay so the the title of the talk is a bit vague what are we going to do today let me just cover that quickly we are going to cover some cocoa programming topics which is good we are also going to be discussing some api's and we're actually going to write some code using those api's we're actually also going to try to compile and run those apps on stage so keep your fingers crossed and probably the overall goal is to demonstrate that cocoa is powerful and easy you've heard this on Monday you saw some demos and we want to show you with more stuff that that's indeed the case now note that this doesn't mean that if you're a new newcomer to cocoa that within two weeks you've written the world's greatest app and you're shipping it there's still a significant learning curve you still have to learn all of the functionality available of the classes and so on but again cocoa is got a consistent set of API some nice small number of conventions and paradigms it uses and as you become familiar with those names you see those you're going to become an expert in hopefully a short period of time and overcome that learning curve and today we're going to cover some of the representative topics that you might encounter in your cocoa programming so before I dive into api's and and some code I want to give you a quick overview of objective-c very quick just so that those of you who are not familiar with Objective C aren't lost in the code examples we're gonna be showing you I should also note that lot of the examples I show you do have one-to-one correspondence in Java it's actually pretty straightforward to use them from Java if you're programming in Java so objective-c is a small superset of C and it's ANSI C so everything you love about NECC and everything you hate about nsec there's probably some is present in Objective C there is some additional syntax and there's a few additional types and Objective C and we'll cover them very soon objective-c also has a dynamic object runtime I I mean two main things by that one it's that messages are bound to objects that is when you call functions or when you call methods and Objective C the binding doesn't happen until runtime which gives you a lot of flexible see secondly objects are able to ask questions about other objects about what messages they respond to that basically Objective C has these facilities that allows you to ask at one time what messages do I respond to what messages do you respond to you know Who am I why am I here etc those kinds of questions and that dynamism actually adds a lot of power it's responsible for a lot of the power and flexibility of cocoa as you'll see so just very quickly cover some of the syntax in Objective C here's how you define in it that this is probably the weirdest syntax it's this is just like a C or Java function except that the header line looks a bit different to you you'll see that it's set with : height : again it's a void return and two floating-point arguments except the name of the method is broken up into two pieces because you can use keywords in front of the various parameters to identify them more easily the rest of the body is you know sir like C or Objective C mixture of those two now to use this in a method here's what the the line looks like you use brackets to indicate that you're making a message send or a method call my rect is the receiving object and they say set with : height : with the parameters appearing in the appropriate places now note that when you this key words that appear in front of parameters really allows you to make the code a lot more readable especially when you have multiple arguments which all are identified by the keywords now one other interesting thing in Objective C is this ability to refer to these methods as I said Objective C is fairly dynamic and one reason for that is this selector type the SEL or the cell type allows you to reference methods and then use them so for instance the reference this method set with height you can say at selector and then put the method name in there and then this variable myself can be used in a variety of contexts for instance you can apply to an object it's store like a function pointer but a lot more dynamic because depending on object you're sending to will actually execute a different body of code depending on how that object is implemented this method will see a use of this later on to refer to object here's how you declare it rectangle Stars says that this object my rect is you know instance of a rectangle or subclass again that's the C syntax it's a pointer to rectangle ID is the generic term for an object which means this some other object is actually an object of any type so these are how you would refer to objects referring to this object meaning the object in the context of a message send the receiving object is self this is very much like this in Java or this in C++ and finally this feature of constant strings this is not strictly speaking this is not a feature of objective-c but something we've added fairly early on the compiler using this app quote business you can create constant strings which are instances of the in a string class and in a string class is a object that's used very heavily in Cocoa API so this allows you to get instances of those very efficiently because they're at compile time okay so so much for objective-c now hopefully now you're armed with just enough to understand some of the stuff we're talking about so how's today's talk format we thought you would ask questions and we would answer them and just to make sure it's all clean and not so messy we thought up the questions you want to ask okay so let's just start diving question number one I wrote a small app for my school project but for full credit I need to support undo the app is so simple I don't know if I can help me okay there's a great question now typically when you think of undo you think of a large app and if you were here for the cocoa overview session you heard Chuck say that undo is easy to add to applications that are designed using Model View controller paradigm and which implies you know well-designed large application not necessarily a small application that's somewhere in Kindergarten road so let's see how we can do this so now the reason you can add undo to any kind of application is Model View controller is actually fairly easy to achieve at least at a superficial level and that's sometimes enough in addition the undo is really not all that hard so you can actually try to squeeze into any kind of application the main object you use to do undo is the NS undo manager so let me just show you a slide with the api's and then I'll jump right into a demo and that's undo manager is the main class you use there's usually one perv or one per document typically you would have one per undo context you want a sport so if you want to have undo that applies to the whole application means undo stack applies to the whole app you would have one instance of this instead of one per window the way you use this is whenever the user does an undoable action you know they type some text they do something you register a callback in the callback is the callback you want invoked to undo that action the way you register this callback is to call this method so note that this is again those of you on these equal objectives this is a method with three arguments this method you provide first of all the callback target who's gonna be called an S selector basically the method that will be called there's the use of that SEL type and finally the single argument into which you can shove anything you want so this is basically what you do okay so this is pretty much all the API I need to show you at this point so let's go and do a little demo okay so for demo I'm going to be using the dot view application those of you who were at last year's cocoa overview probably know that dot view application was born there on stage then it made its way into the examples folder on your ten machine it also made a makes an appearance in the cocoa learning cocoa book by O'Reilly so this program has gotten around and here it is again once again for us to fiddle with okay so the program is very simple it's got one subclass of view let me just run it so there this you you probably have seen this in one of those contexts you can make the dot larger you can click anywhere you want you can also click on this color well object which brings up the standard color panel and you can change the color so if you go look at the Edit menu which is standard in cocoa apps you notice that nothing is enable you can't cut copy paste you also cannot do undo or redo so our goal is to try to enable those okay so let me quit this right now so this this app only has one object it's the dot view object it's a subclass of nsv you as you know in this view is the main object used for drawing so I'm not going to go through all this implementation there's actually only about 25 lines of stuff here you in it did you do like it this is the way you use draw themselves and the interesting methods are Mouse up this is what moves the dot set radius which is what changes the radius and set color which is what changes the color okay so first let's concentrate on making the color undoable now let's look at this method here it takes an ID sender this is that a typical target action method if you remember from Monday or from some of the other talks target action is how cocoa UI objects communicate with the backend objects so in this case whenever I fiddle with the color well I mean the color panel the color well ends up sending me a message and argument here is the color well and here I get rid of my old color dot color is the current color and I hang on to the new color by asking the sender what its color is and hanging on to it and I tell myself I need to display so that's all nice and good but this is not really an MVC this is not a very good MVC method it mixes the model the view and controller all into one so see if we can make it a little better now I'm tired of typing so for the rest of this session I'm gonna use this magic typing assistant and I might explain to you how it works later on so now you'll see how it works I'm just gonna go like this and it's gonna type for me okay okay so let's get started first I'm gonna add this method this assistant is really very good okay okay so I've just added this method which is very much like this method except instead of taking a sender it takes an NS color and instead of obviously asking the sender for the color just retains that color so this is more of a model method you know it sets the instance variable directly that means somebody else can call it to set the color that's nice let's go ahead and rewrite set color to work in terms of set color value and that's fairly obvious as well hopefully it's fairly obvious that this old method is equivalent to this and this so this method just calls set color value with the color right you're convinced that's about the same thing so let's get rid of this so the beauty of doing this is now we have a method here which we can use for our undo purposes okay so the first thing I'm gonna do here is to get a hand and create an undo manager now it turns out that every window by default has an undo manager so if you don't do anything undos work within the context of a window and that's why don't we take advantage of that right now so I'm gonna ask my window for its undo manager by default it's not created it will be created lazily and returned to you and that's what we're taking advantage of here and now we're going to use make use of that code I showed earlier okay so just to make sure you understand this I'm telling the undo manager to register undo a target self self being this object selector is the set color value selector an object is the old color so what happens is whenever I change the color I tell the undo manager to call myself with the old color if it needs to undo this okay so this is pretty much all that's needed and let me show you that that's indeed the case I'm gonna save I'm gonna build and run okay let's hide others okay so the Edit menu is disabled I can click around it's still disabled but I can bring up a color well I can change the color let me actually make this bigger change the color and undo is enabled and I can undo there you go now notice that one more magical thing we do is also enabled so what's happening here is any time and undo is being done any time we do something the undo methods are recorded now when the user doesn't undo that same method is called when that methods being executed it also registers undo so any undo that are registered as a part of processing and undo are recorded as redo actions for that undo so it turns out that one line actually is enough to do both the undo and redo another magical thing if I actually change this around so I'm changing the color all the way when I undo it doesn't go back to the incremental color it just goes back to the last color when I started clicking that's because undo managers not smart enough to know which event mode were looking at and ignore all the events not actually ignore them but call us all the events that happen when we're actually in tracking mode this helps you get rid of methods that happen like this or when a slider is moving and so on that's the right thing to do and again you can override this behavior but typically it is the right thing to do okay so let me quit this and next thing I'm going to show you is let's also make the dot moving undoable okay so here's mouse up here we look at the event location we convert it to the current coordinates converted to store in a variable called center and then we set needs display well now you know how to fix this we want to go ahead and add a method that does a set Center for us okay okay so hopefully this is a pretty obvious method to set the center pretty straightforward it also means I can now get rid of these two lines and replace them by this so self-set Center with that mumbo-jumbo we had earlier so that ends up calling this method okay so let's go ahead and make it undoable just like the other one okay suddenly though you notice one thing that mechanism I showed you takes is an object takes as an argument an object however the set center method takes as NS point and as points are not objects they're structs they're passed by structs so they're not they can't we can't use that method we showed you because it is really geared towards passing objects around so what's the solution to this well it turns out there are two solutions one is you can go ahead and wrap the point or wrap any structure any C type any data structure you want in this magical thing called NS value and then it becomes an object however note that this is really not very pleasant because suddenly have a set center method which takes this NS value as opposed to taking a point and that's not very natural you really want to take a point because that's the argument so we're gonna not use this method and we're gonna use some other method let me just show you the slides for it can we go back to the slides so for sophisticated call backs and undo you would use this method prepare with invocation target suddenly you're all going what's that mean this name doesn't make much sense the word register doesn't appear there so turns out this is this quite sophisticated way of doing this and the name will make a little sense maybe when I explain it but basically this call makes the undo manager go into a state where it then you can make a call into it and it frees drives that call you made okay and then you can layer on add water and execute that call this is a great way to basically freeze dry any call no matter how complicated can have five arguments it can have an argument with a huge data structure it remembers at all and I'm gonna show you exactly how this works so it makes more sense the reason the word invocation appears here is because we use a thing called an S invocation a class called an S invocation to implement this and of course most of this owes a great deal to objective-c dynamic nature able to do all this packaging so let me show you how this works here's the call you make first you call say undo manager prepare with invocation target self again we want this object to be called when this happens and then we actually make the call set center Center that's it you make the call and it just remembers the call instead of executing it it wraps it up and puts it away so I'm going to save on the build and run come back I want to hide others ok so again let's make the dot bigger that's not undoable but if I click here click there click there bring up the color panel change the color around here's green click there click there I can undo it moves undo I can redo undo undo and as you can see the color changes and the movement changes are all stored in the same stack so it all works ok ok well enough for undo let's go to the next question how do I add a toolbar to my application I don't see that interface builder ah that's a good question toolbar as you know is a new object we added it there recently in 10-point oh and most people when they're doing cocoa programming are used to just going to interface builder and dragging their objects off well toolbar doesn't make an appearance in interface builder yet because it's brand-new and we haven't added facilities for a toolbar to properly be archived in interface builder and so it's not there in addition toolbars new so it's not very well documented either so you might be getting confused about how to do it so let's just show you a simple example of how to do this now the toolbars I said is new in Tendo and there are two classes that implement the toolbar the toolbar item class in the toolbar class toolbar item is the class that represents the individual items on the toolbar so the various buttons you see each one is a toolbar item the attributes you can assign to these tool our items include stuff like what the images what the label is what the help tag is what the menu is so when you click on the menu drops you can assign that menu in addition of course very important when you assign a target and an action as you know target action is how UI elements do their thing so you're assigned to a tooltip I'm sorry to the toolbar item and that does its thing note that toolbar items can also be custom by they have a custom view which means if you have some sophisticated view you want to put up there not just a button like thing you would use that mechanism for instance the mail search field which has a pop-up a search field some text over it is implemented using this you can do all sorts of crazy things like this you can put a clock up there a CPU meter stock ticker you can sell ad space on Toolbar so it's all very useful now toolbar items each one has a unique identifier which is an NS string this unique identifier is used to reference the items so it typically the toolbar talks in terms of identifier z' not toolbars and when i say unique here i don't mean a globally a unique you know credit card number like thing it's just a string that's unique within the context of a toolbar and we also provide some built-in identifiers from Coco's so you can use the standard items in your application the toolbar is the class that represents the whole toolbar again it has attributes and these include stuff like whether it's visible whether it's customizable whether it's display mode is and so on in toolbar also has an identifier and this identifier is used to one save the state of the toolbar because remember you can customize those toolbars and when you customize a toolbar in app and you quit the app and your we start if you want the same state in addition this identifier is used to keep the toolbar synchronized with other toolbars so if you're in your app you have seven document windows and you change the toolbar on one of them you want all the other toolbars to change however if you have two kinds of documents for instance in mail there's a compose window and there's a mailbox window you would assign two different identifiers so that when you change the compose windows toolbar the mailbox will remains distinct so that's what the identifier is used for now interesting thing about the toolbar is it's quite a lazy little class it relies and still get to do most of the work so and this is a paradigm we use another place in cocoa for instance a table view would ask its data source for the data and not really store the data itself this allows it to be lazy it doesn't store the data it can create it later you know it's all that's a pretty good paradigm and that's what tool bar does given that's in the case let's just look at the three of the delegate methods these are important delegate methods because these need to be implemented so the first one is how a toolbar finds out what items can be placed on the toolbar now note that this is sent to the delegate so the delegate gets a reference to the toolbar so if the same delegate is being used for multiple toolbars it can make different decisions yeah that's so that that's always the case of delegate methods and this returns an array of identifiers indicating here are all the items that can appear in this toolbar the next method is similar except it returns the initial set of ein items meaning when the user first time brings up that toolbar what today's see and finally there's a method to create the toolbar item because remember all of these methods are working in terms of identifiers eventually somebody has to create a toolbar item from a tool but the item item identifier and that that's when you call this method passing in the toolbar the identifier and a flag indicating whether it's being added to the toolbar or it's being created for some other reason and that would determine whether the thing should be live or not for instance so again these are sent by the toolbar to its delegate okay again demo but for this I'm gonna use the TextEdit application most of you probably know about to take that application it is the app that ships in the Applications folder the source is also available on your developer CD in the examples directory so you can take a look at it yourself so TextEdit is not a document it's not an NS document based application it's a custom document based application it was done before in this document so it influenced its own document functionality and it turns out the most convenient place to create a toolbar is right after we create the window for a document because a toolbar goes hand-in-hand with the window so you basically want to create that toolbar when you create the window and where that happens is in the init method I'm not gonna explain all this code here there's a lot of code but here's the init method which initialize the document that also goes in and creates the window and all that now this is not a super great example of MVC so don't look at text edit for MVC hints but anyway it's it works so at the bottom of in it we're just gonna go create our toolbar here if we look up here a little bit we create the window and so on so ignore all that mess but here let's create our toolbar okay I'm gonna open a brace now one thing people get confused about an objective-c is they think they can declare variables anywhere like in C++ well that's not the case yet because the c standard did not allow it but it's the season 99 and we might actually see this an objective-c someday but for now to create new variables in the middle of your stream in the middle of your code you have to open a new brace again I could have done this at the top but that would be messy so we have a tool bar instance we create the instance note that this is the class a lock in it is what you normally use to clear create instances so here I'm creating a toolbar myself by hand because I can't do it in IV so this is you know work that I wouldn't have to do sometime in the future hopefully and I give an identifier again it can be anything texted a tool bar sounds good now let's go set a few attributes on this we make the delegate to be self we tell it that it allows user customization meaning the user can change it we say that it can save its configuration and we also tell our window let me scroll this up we tell our window that the tool bar I just created is the windows tool bar okay set toolbar when NS window has a method called set tool bar now finally because I gave this tool bar off to the window I don't no longer need it so I release it you know this is the memory management stuff in Cocoa where you create it you hand it off to somebody you don't need anymore you get rid of it okay that's it so that creates the toolbar now remember step two here is the create to implement those delegate methods let's find some empty space here and let's do our delegate methods so the first one was allowed item identifiers here we were supposed to return an array containing the items the item identifiers so let's go whole hog and do this you're going whoa what's that these are all the items that Coco gives you out of the box you know the color dialog the font dialog the print dialog the separate item etc and the customized item so we create an array and we return that okay next we implement the second delegate method default item identifiers and let me finish implementing this here we return an array of just one item this is the default toolbar it doesn't matter what it has the user will customize it hopefully let's just put the customize item in there okay and finally we have to implement our third delegate method remember was to create the items in this case because we were using all the built-in items that method actually doesn't have to do any work but it turns out it has to be implemented so we just go ahead and implement it okay note it's got three arguments we implement it and we just return nil I mean we don't do anything in this case because this method will never be called it just happens to be implement it turns out most of the time when you implement a toolbar this method will be implemented I'll show you that in a few seconds okay that's it we implemented our three delegate methods and we wrote a few lines of code to create the toolbar itself so let's say and let's run this thing okay let me hide others well and there you go there's a toolbar and it has a customized item and it does all the things toolbar does appear disappear that's good note that the content area down here doesn't know anything about the toolbar because that's part of the frame now I can do the magic stuff bring it down now I'm customizing it I can put the colors panel I can put fonts panel let's put this customized item away put a flexible space okay and there we are so that's a toolbar that I can live with if I create a new document thank you again creating a new document also gives me the same toolbar because I told it that it has an identifier and so on so again this is interesting but you really want to create your own toolbar items I mean you're not going to be content with just those items so let's just do that one extra step and show how we would do this to allow that in the allowed item identifiers method we want to return a new identifier again according this identifier is you just pick it out of thin air you don't have to do anything magical let's call that fine dialog because let's say we want to add a button that brings up the find dialog turns out that's one of the ones that's not standard in cocoa so we're changing our allowed item identifiers the default item item fires we don't need to touch we can add it there but we don't need to and finally we have to change this code here the toolbar the creation method because now we are creating a custom item this method will be called with that fine dialog here so let's see how we do that first get rid of this return nil and type away so again we declare a toolbar item let me put some space there so you can see we declare our toolbar item and we created again a lock in it the same thing we're passing the item identifier that we got now we're going to set some attributes if it is equal to define dialog because as I add more dial more identifiers I will get called with other ones too so I'll just make some conditional code so if it is equal to the find dialog I will go ahead and set the label label the string that appears under it I want the label to be set to find typically we would say set label find but that would be a non localizable program and that wouldn't be very good you want to sell in Japan or other countries so why not May localizable by calling this function which allows this string to be localizable you can also set the palet label that is the string that appears in the customization window it can be different than the string that appears in the toolbar I'm also going to set the target turns out to bring up a fine panel you contact this object called text finder this is in TextEdit and we set the action turns out the action to bring up the fine panel is this thing or the front fine panel so again we're setting action and target typically you know when you make connections an interface builder you're implicitly doing this here you're seeing how to do it by hand again because we're diving a little deeper and I'm going to set the image this is the image that appears on the toolbar now to set the image I asked an S image for an image and now I just said that to be my image now here I put a question mark because I don't have an image yet let me go ahead and find an image by going to finder go into my documents directory I'll choose one of these images this one okay it turns out this is a picture of my cat turns out the reason for that is because my cats always finding things under the couch behind the refrigerator inappropriate things but he's a good finder so let's just use the cat so to use that image and this is pretty typical whenever you want to use an image in your application and you want to make it part of your applications resources you drag the image into project builder under resources project builder asks me what to do with it one of the important things you might want to do is copy it into your sources and add it to my target so now that the cat is part of my resources along with all these other resources down here I can actually use this call and s image image named put the word cat here so that method image named will find any image out of your applications resource package if it's the correct we localized I'll find a localized version so instead of having you know an Egyptian cat you want to have a Norwegian cat that's okay so you can do that then we didn't localize it here but that's what you get that yeah okay and then we finished this because we're done and we return the item okay and turns out that's all we need to do now you might be asking what's this order release business again that's got to do with Coco's memory management because we created the item and because we're returning an item that the clients gonna take ownership of we auto release it which means release it later it's sort of like smart garbage collection and you will see this a lot and it's standard particle programming up not gonna go into it anymore so that's it and note that if you had other items you'd basically write code like this or someday maybe use interface folder and not have to do this at all so I'm gonna save I'm gonna run okay hide others okay there note that when we ran it it remember the old toolbar so that seems to be working bring down customize there is the fine dialogue there's the cat let's say done and let's see if the cat can find things there's the fine panel so there you go okay so you know we could play with the toolbar all day long but that's okay let's go back to our next question question how can I get a better framerate out of my animating game oh it's a performance question that's great and you've been hearing that performance all along so let's see how whether we can do this Oh demo again okay okay let's see about this animating game now let's see what what it does what it looks like conveniently it's on our dock oh it's a worm game okay so this games been around for a while I think since the 60s and it even makes appearance on your cell phones you know you probably have seen this game let's run it just to show you what it's about I'm gonna start there you go now typically this worm game doesn't run this fast in fact I can make it run slower by clicking on here there you go what you do is you make the worm go eat the target oh yeah and when he eats it he grows by one dot so as he gets longer and longer he becomes harder to manage it and eventually it hits itself and dies and obviously the more you eat the more you get and typically the worm when it hits the edges would die but we simplify the game here for demo purposes because I don't want spend too much time playing the game so this slider here allows us to change the framerate and I'm setting the framerate to a really high number and you can see I'm getting 38 frames a second okay that seems good enough for this game well I mean you know this person is quite worried about performance but it's actually good to be worried about performance even if your framerate is good trying to speed it up means that there's more processor power in the machine for other things and you can be doing other things in the back so let's see whether we can help this person out now one thing you'll notice here is that this whole area seems to be white and we don't see any of the window background typically when you subclass a view you either draw everything in your bounds or you draw less than everything now if you draw everything one thing you can do is tell the view subsystem that you really don't want anything behind you to be drawn whenever you're being drawn and the way to do that is to implement one method in view now whenever you're doing a drawing a subclass of view a drawing application this is the first thing you should look for and that's to implement this method called is opaque to tell the system that your opaque that's the first thing we're going to do let's see if that will help us now we go to our subclass of view in this case room view and it's some fairly involved overview class there's also a controller class to control the UI and the worm guts which controls the logic of the game let me close this up so this is again a standard view you know in it with frame there's a dialog there's a method to set the string and get the string oh yeah if you notice the worms body was made up of a string that seems odd but you know there's a reason for that later in the demo there's a method that performs each frame of the animation and finally there is the draw rect method draw rect again is the method you override to do drawing now if we bring up our fine panel and search for is opaque we see that it's not implemented so let's first thing we should do is go implement that okay it's implemented just like this is flipped method it's so easy I don't need my typing assistant is opaque so we implemented and we returned yes because the default implementation returns no and this basically says that when this view is being drawn don't worry about drawing anything that's behind it because this view will take care of every pixel within its bounds so let's run this little puppy well look at that 44 frames a second so just that one little line got us you know up from 37 to 43 42 so that's that's pretty good but you know I have a feeling this is not gonna be enough let's hide the project builder so next thing you might want to do is run quartz debug which you saw earlier in the week I hope quartz debug shows you which areas are being drawn let's kick it on okay so again obvious you know this might have been a rigged demo but it's obvious that the worm is drawing the whole view every time okay the yellow area shows the area that's being updated well you really want to worm to only to draw the area that's being updated so that's next optimization we can do so let's quit the worm let's hide quartz debug and let's go back to our worm application okay now there are two pieces to drawing less than your whole view one is to make sure that when you tell the view it needs to be updated you tell it what region or what rectangle needs to be updated and the second thing is in your drawing method pay attention to that rectangle so we'll do both of these right now so the first one happens here in the perform animation method we say self set needs display yes that just says I'm dirty we draw me and it gets drawn later on whenever appropriate so instead of doing that we have to compute a smaller a tighter rect and let's see how we might do that now some of the stuff here has to do with the worms logic but basically what wanna do let me push these lines down a bit I want to start with I wrecked and I'm gonna remember the old target position and I wanna for the length of the worm I want to look at every position every body position of the worm I'm gonna figure out what the rectangle is I want a union into my rectangle so as a result of this operation I end up getting a rectangle which tightly covers the worm okay so again you know that little method there returns the worms body and so on so this allows us to create the tight body around the worm okay then we update the gamestate meaning we move the worm now it turns out we know that the worm only moves one block per frame so after the game has updated the frame we can go ahead and Union the new head position okay again the worms head moves so we also want to bring that rectangle into the whole rectangle so our rectangle grows of it there's one more thing we need to do to compute the tight rectangle and that is to see if the target changed position meaning if the worm ate the target it moved so let's also Union that end if the old position is not equal to the new position we go ahead and union in the target position okay so I hope this makes sense now we have a rect that includes the target in the worm it only includes a target if the target moved which is rare enough so that that's okay and the final thing we have to do is instead of Sidney's display we call sit needs display in rect and pass that rect so now that tells the view machinery just draw the smaller rect so what's safe the next thing we want to do is modify our draw rect know that note that draw rect is taking a rect argument but nowhere in here it's really being paid attention to again sloppy programming first thing you want to do is this is the background drawing and we do a rect fill of the whole balanced self bounds means my whole bounds here itself is the view so instead of self bounds we really want to pass in correct okay so that's straightforward we just draw a smaller rect the next thing I want to do is note that here we take we run the length of the worm take the rectangle and we draw the character the substring that makes up that part of the worms body and we do it character by character so instead of doing it all the time unconditionally let's do it if they're rect intersects the rectangle that was passed it okay does that make sense again we only draw it if the worm is in that region again pretty straightforward this will intersect the two records and return to you yes or no finally the same thing with the target if the target rect happens to be in that wreck we passed in we'll just go ahead we'll only do it if the target rect is also in that box okay so I'm gonna save I'm gonna run okay here's the moment of truth okay so there's 85 I think that's fast enough do you think so you agree okay good so there you go we've now made the game quite unplayable but it's also very fast so I think I think this this person should be pretty satisfied with this performance okay so let's go let's go back to the slides please okay so what we learned from here is that you want to draw as little as possible one thing that means is you should fine-tune the drawing area the update area and you should also pay attention to that you should also use is opaque to prevent super views from drawing needles see those are probably two most obvious things you can do to speed up drawing and also use quartz drawing to see what's drawing sometimes you might find something very surprising like some text field is being updated every so often and you don't even know about it or as Robert Schroder on Monday even when paused his application the kissflow kept on drawing now there are things like that that courts the debug will tell you next question hmm but still not good enough for my boss can I make it draw even faster okay so that's interesting we'll see if we can make it draw a little faster I think the thing to do at this point is to see whether we can see what the problem is so let's go back to a demo again and will now use another performance tool quickly let's run it and let's launch sampler again I think you heard enough about sampler I'm not gonna go into details with sampler you can attach to a running program I'm gonna do that and I'm gonna choose worm and I'm gonna say okay is you've seen sampler so I'm not talking too much about it but what its gonna do is it's gonna sample the target app every so often every 20 milliseconds and capture the stack and that's gonna give us an idea where the application is spending its time so let's put this down here let's say start there you go let's say start sampling being sort of paced back and forth a bit get some coffee its sampling the worm and you can say stop okay and let's stop the worm here okay so this is now the biggest stack now you can actually go down this tree here and look at all the things that are happening but this turns out to be the biggest stack let's go back and if you'd look down here its main its application run these are the standard objective-c things I'm savanna cocoa things which are powers of frameworks and here the worm timer callback this is your code and here we're displaying the view and it turns out the biggest thing we're doing and displaying and you would expect the displaying to be taking the longest time the question is what is the displaying so slow turns out the biggest thing here is nsstring string drawing draw in rect so the most time in fact of all the drawing that's happening 90 something percent of the time is spent in drawing that string okay so maybe that's something we can look at okay so let's go take a look at that slide squeeze okay to do to draw strings to draw short little strings here and there you would use this API NS string draw interact with attributes its the rectangle and attributes include stuff like the font the color you know everything else a style text would need to know this math is very convenient and you should use it if you need to draw strings here and there but it does do a lot of work on their covers one of the things you need to do when you're drawing true Unicode text is that you need to you need to take the unicode string you need to convert it into what's called glyphs and then you need to lay those grooves out and you need to send them to the screen so it's not just a simple matter of taking the Unicode characters out of the string and blasting to the screen the reason for this is Unicode text is fairly complicated and you basically need to convert those unicode's into elements in the font which are called glyphs and sometimes like a three character unicode string might correspond to five glyphs or it might correspond to one glyph because there might be a special glyph some languages are actually even more complicated so that's why the text layout machinery is actually does a lot of work in addition there's a lot of work that needs to set up just to start that operation and end it so the string drawing is convenient but because it's called with no context it does a lot of work repeatedly so here we can try using the text system for some performance gain and to do that let's look at the tech system architecture rather quickly some of you might have seen this before the cocoa text system is a network of objects typically when you're using it an interface builder you're making you're copying that you're taking an instance of NS text you drop it into your application and it creates everything else for you and then you're fiddling with that but these other objects are also available for it to use directly oops text storage is the model object it stores the characters and their attributes layout manager computes and stores the glyphs in their locations so the layout manager sir like the controller in this picture text container provides text area information so in fact in the spec you can imagine a layout manager with multiple text containers if you are doing a multi-column text editing application for instance in the text view the final piece the piece you see in interface builder the divisible piece is the piece that handles a display and editing now note that again this allows us to do fairly sophisticated things for so you can have one text storage you can have three layout managers what this means is you can have a same text document but it has three different views on it so one could be you know a wide view one could be a short view one could be a view without fonts and so on similarly multiple text containers as I said allow you to have multiple pages multiple columns so on so turns out that here the interesting piece when they use is the layout manager it gets the text contents from text storage as I said it converts these characters into glyphs and it computes the glyph locations and what we really want in this case is we only use the glyphs in the Gulf locations and we don't want this real eye out to happen over and over and then finally you would get at layout managers to draw these glyphs by calling this method draw glyphs for glyph range and that's usually called by the textview layer so let's see how we can make use of layout manager in our application first thing we want to do let's get rid of this is we want to go into our room view the dot H which is our at the header file which declares the object and want to create three when I declare three new instance variables text storage layout manager and text container so those are the three objects we talked about so instead of using text view we don't need text view we're just gonna use those three level lock three objects at the bottom so we create them let's save our header file and let's switch back now in the init method where we create various stuff we now want to go ahead and create those three objects and it turns out it's fairly easy to create them text storage a lock in it layout manager a lock in it text container a lock in it we don't want to provide any sophisticated at you know attributes you can do that you can provide size as you can provide various other properties we don't need to deal with us right now and then we want to add to the layout manager the text container and add to the storage delay our manager again the API says and not set because you can have multiple layout managers you can have multiple containers okay so this is all at me all we need to create a subset of the text system again note that when you create a text view programmatically or through interface builder all this is done for you magically because that is really the you know the most common use of the text system okay now because we created those three objects we should remember to release them so whenever object goes away we release the three things we created that's fairly straightforward now comes the tricky part set string is where a new string is provided for the worm note that this happens very rarely because the string is not really changing okay so what one to do is whenever we need get a new string in addition to remembering that string we actually want to pour it into this text system that mini text object we created and to do that I would tell the worm storage object that its string is the new erm string that I have in addition I would tell the worm storage what the attributes are now this worm text attributes comes from up here and again I said it's the style information in this case it just stores the fact that the font is loosely round of 16 I'm not going to go into that so anytime a new string comes in we reinitialize our text system with the new string and the new attributes that's it that's all we need to do there okay so that takes care of that piece and finally in the drawing instead of doing this string drawing rec which we know is not fast enough we want to use a layout manager to draw okay so instead of doing this character stuff let's open up some space here let's push this to the top I'm gonna work in terms of glyphs I'm gonna ask the glyph location and I'm gonna do draw and glyphs not ignore this code here you know I can explain it but it's really pretty straightforward what's happening here is instead of drawing the character instead of drawing each character one by one as we would do down here we're now drawing each glyph one by one and pour that we're going to the layout manager and I can get rid of this code so the old code and the new code are very similar it's just that one is a slightly lower level talk talking to the layout manager and turns out this is all we really need to do and again I'm saying all we need to need to do but this is actually fairly sophisticated stuff because you have to dig down you know in there into the text system and it could get messy but let's see if it gives us the performance we want let's build and run okay oh look at that so I think that's good enough for this person right now okay at this point I'm getting really sick of the worm hey that's sweet okay add some pizzazz to the app oh and we're shipping this afternoon so something quick please oh I see it's still a worm question okay so we need to add disaster this app and we need to do quickly okay so well what can we do the app looks pretty boring let's go back to it quickly there's this big white area that's quite boring right so we can add some color to it now if we go back to our draw rect which is here one thing you notice is that we do an S color white color set that makes the background white well obviously we can add pizzazz and then very quickly by making this red or yellow or anything you want but that wouldn't be enough pizzazz I don't think for this person so let's do something fancier instead of color but we might want to use an image or a pattern one good place to find images or pad well there's a cat but other than that if you go into the desktop pictures folder on your disc there's a bunch of nice pictures here's one there's another one so on now one that I like that will work probably in this case is one of these ripple patterns now I know if you can see it there it's a nice little pattern with a little thing and so instead of using an image let's use a pattern and let's see how how easy or hard that is now as I showed earlier we want to drag this image into our let's get this back we want to drag this into our application like we did earlier let's copy it in those resources we want to copy it we're gonna say add so now again this image ripples Maus dot jpg is part of my application now okay and now let's go ahead and use it turns out to use a pattern where you can use NS colors so therefore this logic here of setting a color and drawing with it doesn't really need to change very much let's go back to our view and let's add an instance very for the color okay so now we have an additional instance variable on top of everything else we did called color now back in our view implementation where we create all this other stuff let's go ahead and create that color and that requires one somewhat long line but there it is what we're doing here is like we did before we do in the image named ripples mas which takes that image that corresponds to that thing and when we call make this call to NS color saying color with pattern image that says create a color using this image as the pattern and then we retain it because we're gonna hold on to it and that becomes this new color instance variable we created now again being a good citizen you wanna release that when you go away and finally down in our draw rect instead of this red color which wasn't too creative we'll use color okay let me save ah look at that and if we let's also set the speed down to something nice and let's run actually you can set the speed to something high and you see that the frame rate actually isn't really suffering because of this maybe just a bit but it's the whole pattern and note that this is a pattern and it's being drawn continuously so if I make the window larger you actually see the pattern again working there so just by using an image for the pattern just with one extra line of code you're able to use patterns and sort of colors in your application so that's fairly straightforward Killick okay let me say some words about NS color in s color therefore it not only represents colors but represents meta colors catalog colors patterns etc and to paint with any one of those you just do NS color set and here are some of the interesting methods we just show color we just shows saw color with pattern image another one which we saw is white color that just gives you the white color you have red color orange color blue color whatever you can create a color with your own RGB values obviously that's color with calibrated red so on RGB alpha that's what you're used to and finally we have meta colors like window background color this is the color that presents the background color of a window and turns out that actually returns to you the Aqua pattern if you need to use it so again a patter use of pattern in colors okay question let's see how much more time we have for questions so how does the magic typing assistants work go ahead you ask okay the answer is services okay and some of you might have guessed that if you are seeing a little mini flash services allow applications to provide their functionality to other applications in this magic code we were using is actually a modified version of the TextEdit application all we did is we implement this service where every time you invoke it it takes the next line from the currently open document and texted it and paste it into the current location I'm at now I'm not going to go into detail and services here because the next talk actually has a little more technical discussion of services so I'm going to leave it there but let me just show you what I mean here by this low feature okay I'm gonna quit the worm so here we are in project builder again if I click here in text if I go to the services menu you'll see that there's the standard services you're used to seeing and then there's this text edit + item which is the app I wrote the modified version of text edit in addition to the standard text set items there's a get next line move down the line and move up a line and it's been assigned key equivalents again through services that's fairly easy to do so every time I go ahead and invoke this service get next line it gets me the next line see that's the line I was supposed to type but I did by hand again I can do it and you can I can move up by hitting that thing and it does the same line again and again you know you can get very fast and you can see that you can do anything you want and some services work by actually taking the current text selection and working on than returning a new thing and so on and again I'll leave a discussion off to the next talk okay slides please okay so let's talk about what we did today I think we're pretty much out of time we added undo to an unsuspecting app we added a customizable toolbar to texted it we made a game draw much much faster that was like 8x that's pretty good and we also learned how to use patterns to spiff you up any app and we saw how useful services can be so again a bunch of topics and a representative set of topics that apply to actually a lot of applications so what we really saw is you know how to enhance apps with just a few lines of code and again use your visible way and did you know you can apply this to any application and you also saw how to do fairly sophisticated things with a little bit more of code I mean that ten lines of code you saw where we're using the text system and deaf that's actually code you wouldn't normally use but again just by diving in a bit learning a few more classes and again you know there's a learning curve but learning those few classes you're able to do a lot more than you can and again those text system objects for instance can be plugged in and very creative ways to create fairly interesting text editors not just texted it we have a saying in Cocoa where we've been you know saying this for many years and I think it's full true we like to make simple things simple and complex things possible so again just with a few lines of code you can come on stage and make a demo but by writing bunch more code you can actually feel magical things that allows you to create a fairly large very you know full-featured application okay as far as a roadmap for other talks now if you miss these first two talks I think they would be very useful if you're new to cocoa and this is the first cocoa talk you went to I would definitely recommend seeing at least those two and maybe some of the project builder talks on on video there they're quite handy interface builders very we don't see interface builder today but it's very integral to cocoa development and the cocoa overview gives you a good overview of the things cocoa provides advanced cocoa topics is right after this one and that's going to be somewhat more substantial talked in this where we're gonna go into some of the advanced features in cocoa file wrapper etc drag-and-drop printing you know how to dive into those features are cool performance tools if you're more interested in learning more about sampler etc is also at the same time or you can catch that one on video it's in room a2 and finally we have a feedback forum if you can't get your question answer today or you have something to say it's tomorrow afternoon at 5:00 and Heather Hickman the art is our technology manager and the cocoa feedback and the cocoa development mailing lists are available for your use you