Cocoa Programming for Mac OS X - Aaron Hillegass [127]
More on CALayer
CALayer allows you to control quite a bit about its appearance through its properties. But what if that wasn’t enough: What if you wanted to do custom drawing in a CALayer? The CALayerDelegate method drawLayer:inContext: allows you to do just that with Core Graphics/Quartz.
However, much of the time, you will simply want to control a few common things:
• An image
• The background color
• Whether the corners are rounded and, if so, how much
• An image filter to run the contents of the layer through
Subclasses of CALayer make particular kinds of drawing easier.
• As we saw, drawing text on a layer is easier if the layer is an instance of CATextLayer.
• CAShapeLayer makes drawing a stroked and/or filled path simple.
• CAGradientLayer displays a configurable gradient.
• Getting OpenGL calls onto a layer is easier if the layer is a subclass of CAOpenGLLayer
• The base layer of a view is an instance of _NSViewBackingLayer (not a public class!) that knows to draw the contents of the view upon itself.
Challenge 1
Add a text layer to each image layer to show the filename of that image. You will need to supply an additional parameter to presentImage:. Experiment with adding shadows and borders to the layers.
Challenge 2
Add a button and a text field to the window. When clicked, the button should reposition all the image layers but not the rounded black text container layer! Use the numeric value from the text field to set the duration of this repositioning animation.
Chapter 34. Concurrency
Until now, all the applications we’ve written in this book have been single-threaded. In simplistic terms, this means that only one thing is happening in the application at any given time, such as responding to a button click, updating the display, or counting the number of objects in an array.
Of course, in some cases, it’s very useful to be able to do many things at once. In a modern operating system, each application is running in its own process; this division gives each application its own memory space, but it also allows the task scheduler to create the illusion that many applications are running at once.
Multithreading
Threads give this same power to individual processes. Each thread in a process has its own stack, meaning that each thread can be executing its own code path and has its own stack variables. The heap, however, where objects are allocated, is shared among all threads, as are global variables. Each process starts with one thread, referred to as the main thread. Additional threads, called background threads, can be created at any time and will be scheduled to run concurrently with the other threads in the process. This is called multithreading.
In Cocoa, the display is always updated by the main thread, which is also responsible for handling events from the window manager. Thus, if your application’s main thread is busy calculating the value of pi to 6 trillion digits when the user tries to resize the window, the window will appear to ignore the mouse input until the main thread gets back around to processing events. Calculating pi is a great use for background threads. Hardware I/O is an even better candidate, as hard disks are notoriously slower than processors and RAM. If your application calls for synchronous network communication (asynchronous will not do), a background thread will allow life to go on in your application’s other threads even amidst network hiccups. By using multithreading, your application can remain responsive to the user even while it is deep in thought.
The emphasis on multicore processors over the past several years has led to a number of Mac OS X improvements, namely NSOperationQueue and Grand Central Dispatch, that make multithreading much more accessible to developers. In this chapter, we will look at NSOperationQueue and some other methods for creating background threads.