Online Book Reader

Home Category

Learn Objective-C on the Mac - Mark Dalrymple [117]

By Root 1005 0
the labels and blend views down a bit and make room for another label entitled Blend Modes. Make it white as well, and use the font panel to make it a bit bigger than the other labels. Save your work, go back to Xcode, and Build & Run. Figure 11-7 shows the completed window as it appears in Interface Builder, alongside the running app.

Figure 11-7. ColorMix in its final form

Now that the application is up and running, you can use the standard menu items to create multiple documents, specify different colors for each document, save documents, close them, manage their windows, and so on. Cocoa’s document architecture takes care of the details of instantiating your documents and document controllers, loading nib files, using a Save panel, and more. All of these features can be enhanced by the developer (e.g. you can customize the process of saving documents in various ways), but you can also go quite a long way using just the basic functionally that works right out of the box.

About Undo and Redo


At this point, we should mention NSUndoManager, which handles undo/redo support in Cocoa. You may have noticed that the actions you perform in ColorMix (really just changing colors) are all undoable, and redoable, via items in the Edit menu. Also, you may have noticed that these undo and redo actions are document-specific; making changes and undoing them in one document is completely separate from whatever happens in other documents. What’s probably not so clear, however, is just what’s enabling that functionality; we haven’t written any code to deal with undo and redo, and yet there it is. The short answer is this: in a Core Data application, basic undo/redo typically is taken care of for you, and you don’t have to do anything. The managed object context that deals with the model objects is able to notice when an object is edited, and add an inverse operation to the “undo stack.” The upshot of this is that, for most modern Cocoa apps, you get undo and redo for free.

However, this is a book about programming, not about listing cool features of the frameworks. At the very least, you need to know a bit about how the underlying pieces work, so you have some idea where to tweak things if necessary. So, here’s a crash course in how undo/redo support works in Cocoa, and how Core Data and NSDocument conspire to make it work automatically.

The Undo Stack


Many programmers have probably never given much thought to how undo and redo are typically implemented in an application. It’s one of those things that have become so universally accepted and expected that it seems like it’s just part of the natural order of things. The basic premise is this: each time you edit something in your app, an item representing the reverse of the editing needs to be created. So, if the user adds the letter “X” to the end of a piece of text, a piece of code needs to create a representation of the opposite, an operation that can delete that same “X.” That representation is then placed on a stack of similar items somewhere (the “undo stack”). Invoking an “undo” command consists of popping the most recent item from the top of the undo stack, and performing the action it describes. At the same time, invoking an “undo” command ends up creating yet another item, the reverse of the reversed item from the undo stack (the same as the original edit, in fact), and placing it on a “redo stack”, in case the user later wants to undo the undo.

This architecture has variations, such as limited stack sizes, or just single undo items without any stacks at all, but the basic architecture is pretty similar across most platforms. One thing that’s pretty special about Cocoa’s way of implementing this is that, instead of representing each undo item in a special form that has to be later decoded in some way, each undo item is constructed implicitly using the target object, the method selector to be called on it, and whatever arguments are required. When the “undo” command is triggered, there’s no decoding or lookups of any kind. The method is simply invoked

Return Main Page Previous Page Next Page

®Online Book Reader