Online Book Reader

Home Category

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

By Root 927 0
This powerful technique lets you extend Apple’s own classes in ways that Apple never anticipated. You have to exercise caution when doing this, because there is always a risk that method names may clash if both your code and some third-party code include identically-named methods in a category, or if Apple adds a method with the same name in a future version of Cocoa. But that risk is well worth the rewards to be gained by improving your code’s readability.

To do this, start by creating a new pair of source files in Xcode, called FoundationAdditions.h and FoundationAdditions.m. The simplest way to do this is to create a new class called FoundationAdditions, then remove the @interface and@implementation sections from the .h and .m files. Then add the following code to the two files:

That code adds a method to NSObject called operationForSelector: which returns an appropriately configured NSInvocationOperation instance. To use this in your controller code, add the following line to SlowWorkerAppDelegate.m:

Then, replace the NSOperation creation code in doWork: with the following:

Ah, isn’t that better? To format things for this book, each operation creation takes two lines, but if you’re editing in a window that’s just a little bit wider, each of those will fit nicely on a single line.

Demanding the Main Thread


Now, we’re still not quite ready to roll. Remember that earlier in this chapter, we mentioned that the AppKit classes (such as all the window and view classes) are generally not thread-safe. All access to them should be performed exclusively on the main thread. However, we have this finishWorking method that runs in an operation, and will in all likelihood be run on some other thread when its time comes!

To get around this problem, we’ll drop down to the NSThread class, which provides facilities for checking which thread we’re running on, and for calling methods on background threads or the main thread itself. Using NSThread, we can check at the start of finishWorking to see if we’re currently running on the main thread, and if not, do so! Here’s an initial implementation:

Our method now first checks to see if it’s running on the main thread already. If not, it relaunches itself on the main thread, and returns so that the rest of the method doesn’t go on executing on the non-main thread. Then, when the method is relaunched on the main thread, it continues on through and does its work.

Once you get started working with operation queues, you may find yourself need this kind of functionality in a lot of your worker methods, forcing them to run on the main thread in order to update the GUI. What we’ve just shown can be improved a bit by putting it into a C preprocessor macro. Because this is essentially adding functionality related to another Foundation class (NSThread), let’s go ahead and put this into the FoundationAdditions.h file we created earlier:

There are two “tricks” to point out in that snippet. The first is that each line (except for the last) ends with a backslash. The appearance of a single backslash in a C preprocessor macro (in case you’re unfamiliar with it) causes the preprocessor to ignore the next character it finds. In this case, putting it at the end of the line makes it ignore the following carriage return, so that it goes on to interpret the next line as part of the macro (make sure you don’t have any empty space at the end of the line, otherwise this won’t work). The second trick is that instead of naming a selector as we did initially, we’re using a special variable, available to the preprocessor at compile-time, called _cmd. The _cmd variable always contains the selector of the current method.

With that in place, we can force main thread execution of any of our worker methods by simply starting them off like this:

Now you should be able to Build & Run your app, and you’ll notice something perhaps a little different after pressing the Start button: the button immediately reverts back to its non-clicked state, and the menus still work. After about seven

Return Main Page Previous Page Next Page

®Online Book Reader