Today we started off learning how to play audio and video files bycreating a simple application that allows you to play a system sound,an audio file, and a movie. If all you want to do is play .caf, .wav.or .aiff audio files tat are less than 30 seconds in length, you're inluck because you can simply use
AudioServicesCreateSystemSoundID to register a sound with the system and then use
AudioServicesPlaySystemSound to play the sound. On the other hand, if you want to play almost any type of audio file, you can use the
AVAudioPlayer, which really isn't all that much more complicated. You create a
AVAudioPlayer and then implement
AVAudioPlayerDelegate methods like
audioPlayerDidFinishPlaying to respond to audio player events. You simply call
stop to control playback and you can use
isPlayingto check playback status. Recording audio is apparently more difficult,and we didn't really cover it in lecture or lab, though the exercisebook has a whole appendix devoted to creating your own voice recorderapplication.
For movie playback you can use
MPMoviePlayerController. It is also pretty easy to use. But, one caveat is that it completely takes over your iPhone application when you call
play, and the user has no control until the movie ends or until the user exits your application.
Low Memory Warnings
We next took a (very) short detour talking about low memorywarnings. When your application is taking too much memory, the iPhonesends your application the
applicationDidReceiveMemoryWarningmessage. In that method you are supposed to release as much memory asyou possibly can. However, according to Joe, the iPhone does not reallyprovide much information about how much memory you need to release, orhow much memory will cause a low memory warning in the first place! Joesays to just release as much memory as you possibly can immediately orelse the iPhone can simply terminate your application. All your
UIViewControllers are sent
didReceiveMemoryWarning. The default implementation checks if you have implemented
loadView,and if so releases its view instance. The next time the view needs tobe shown on screen, it gets reconstructed. One last thing is that theiPhone simulator allows you to simulate a low memory warning via the"Simulate Memory Warning" option on the Hardware menu.
OpenGL ES is theimplementation of OpenGL on the iPhone. Basically it is a low-level CAPI that allows you to draw 2D and 3D graphics on the iPhone in variouscolors and textures. Triangles, lines, and points comprise the basicgeometrical shapes you can use to compose graphics. When coding OpenGLES you basically need to define all the vertices in two or threedimensional space, then define the color of each vertex, and then, viathe
EAGLContext, render the graphic. The color of avertex is defined in RGBA8 format, which allows you to specify red,blue, green color channels and an alpha transparency channel, using8-bits per channel. The
EAGLContext is the bridge between Cocoa Touch and OpenGL ES, and is what allows you to use OpenGL on the iPhone.
When coding OpenGL ES, you use various buffers. The frame bufferdescribes one frame of drawing. The render buffer contains the pixelscreated by drawing commands sent to the frame buffer. When you draw tothe screen, you really draw to a
CAEAGLLayer object, andyou use a timer to request drawing updates, e.g. schedule a timer toupdate the drawing 60 times per second creates a 60 frame per secondrendering. Another important thing is that you must call
setCurrentContext on the
EAGLContextbefore performing any drawing commands. Last, according to Joe, OpenGLis not at all forgiving if you screw something up, for example if youhave an empty buffer or mismatched vertex data in the buffer. When thatoccurs, your application simply crashes.
The lab exercise for OpenGL was to create a "Fireworks" applicationthat randomly generates "fireworks" using OpenGL and that simulatesthose fireworks exploding and then burning out. Pretty cool stuff, butman is it a lot of code to just to create relatively simple thingsbecause you must fully define all the geometry and colors and then useOpenGL functions to enable various drawing states and draw thegeometry. You also of course need to implement logic to change thedrawing over time, for example once a firework explodes you need todefine the logic to animate the particles using lots of math and evensome good old physics equations to compute position, velocity, andacceleration. I bet if they taught physics by having students implementparticle engines on the iPhone more people would be into science!
After various types of pizza, including a really good barbequepizza, for lunch, we learned about using textures in OpenGL ES. You useper-pixel coloring to spread an image file across geometric primitives(triangles, points, and lines). Textures add depth to a scene and canalso be used to create shadow effects and is how you draw text usingOpenGL. We extended our Fireworks application by adding texture to eachexploding particle. Essentially you pin an image file to your geometry.Since adding textures is still OpenGL coding, it is low level andrequires a fair amount of code to define the mapping coordinates forthe texture in order to pin it to the scene geometry. But the endresult is pretty cool!
Before getting into touch events, we took an afternoon hike. It wasreally nice and I wished we had done the zip lines at Banning Millstoday, since it is supposed to rain tomorrow. When we got back from thehike, we plowed into how to handle touch events on the iPhone. Firstup, Joe told us all about
UIResponder, which is the base class for
UIApplication.Because of this inheritance relationship, subclasses gain similarfunctionality automatically for handling the different phases for
UIResponser. The phases of
touchesEnded. These phases allow you to handle all kinds of touch events, including up to five simultaneous touches.
UITouch object is what you work with when handlingtouches. By default, multi-touch is not enabled, so you have to enablemulti-touch either in code using
setMultipleTouchEnabled:YES or you can set the property in Interface Builder. Each of the touch callback methods, for example
touchesBegan, sends you the touches as a set of
UITouch objects and a
UIEventobject. You can use the event object to determine the number of touchesand respond appropriately. In the lab exercise we extended theFireworks application to respond to single touches, touch-and-drag, andmultiple-touches. When handling multiple touches you need to use mathand geometry to figure out things like how far apart the touches are;in the Fireworks application we made it so the further away the touchesthe faster we disperse the firework particles.
Last for today was Core Graphics, which allows drawing in CocoaTouch. Core Graphics is much simpler to use than OpenGL but is not aspowerful. It is not designed to draw super fast animations and gameslike OpenGL is, and according to Joe should mostly be used for UIswhere you need to do drawing.
You use the
drawRect method to define your drawing commands. You draw to a
CGContext graphics context. The main iPhone run loop, not you, is responsible for creating the graphics context and calling
drawRect;you simply need to define what to draw, not when to do it. The basicprocess you follow to draw is as follows. First, get a reference to a
CGContext graphics context. Second, create a
CGMutablePathRefpath object and then draw points, lines, curves, and shapes to thepath. Next, you set the color of the graphics context, and finally youstroke or fill the path object.
During drawing you can save and restore the state of a
CGContext.For example, you might perform some drawing commands, then save thecontext state, change a few drawing attributes and perform several moredrawing operations, restore the context state, and continue drawingusing the original state. According to Joe, you should not save/restorestate a lot or it can really slow down your application.
Core Graphics uses the "Painter's Method" when drawing objects onscreen, meaning objects are drawn from back to front. Objects drawnlater are drawn over top objects that were drawn earlier, effectivelyreplacing the existing pixels. One other thing to mention is that,using Core Graphics, you can do 2D transforms applied to
CGContext to perform rotation, translation, scaling, and skewing of the shapes on screen.
My brain is starting to hurt after three days of hardcore learningand coding. Several of us started watching the Bourne Ultimatum afterdinner on the nice big flat-screen TV in the Banning Mills lodge torelax a bit.
OpenGL, while powerful, is not what I'd call the most fun API I'veever worked with, and it would probably take a while to learn the insand outs and become an expert in it. Adding textures using OpenGL canreally spice up your application and make it look better. Our Fireworksapplication went from exploding popcorn before adding texture tolooking like real, exploding firework particles after the texture wasadded to the particles.
Being able to handle multi-touch events is just plain cool.