Feeds

String theory and the OS X AppKit

Colorful language

The essential guide to IT transformation

Mac Secrets Much of the time, we're off exploring some framework such as GraphKit or the media browser. This time it's the turn of AppKit itself, the framework that's guaranteed to be used by every self-respecting Cocoa app. Strange as it may seem, there are plenty of undocumented goodies here, too.

Let's start with localization, This is the process whereby you build a Cocoa application in such a way that it will display any needed text strings in the default language set by the user. Ordinarily, this is done through judicious use of macros such as NSLocalizedString, the various foreign language strings being located inside the appropriate ".lproj" directory.

However, for those who are lazy and like to live dangerously AppKit provides a routine which provides effort-free localization, provided that the string you want to localize is one of the ones provided. First, you need to define the routine, _NXKitString, like this:

extern NSString * _NXKitString (NSString * tableName, NSString * keyName);

Because _NXKitString (note the underscore) is part of AppKit, there's no need to link with any other libraries or frameworks. The routine takes two parameters, the name of a string table, and an identifying key within the table. It returns an autoreleased string, localized for the current language. You'd use it like this:

NSString * cancelString = _NXKitString (@"Preferences", @"Cancel");

Thus, you'll get back "Cancel" where English is the default, "Annuler" in French, and so on. Of course, this will only work as long as the string you want is contained in one of AppKit's internal string tables. To see what's there, navigate to the following location:

/System/Library/Frameworks/AppKit.framework/Versions/C/Resources/

From there, you can navigate into the English.lproj directory, for example, where you'll see a list of string table files, all of which have the suffix "strings". These represent the allowable table names that you pass to _NXKitString. So, "Preferences" maps to Preferences.strings and so on.

If you examine the contents of each string table file - they're just plain-vanilla text files - you'll see the available keys for each table.

If your application has a very simple, restricted interface, you may be able to get by with just the available strings. It would be nice if "Yes" and "No" were included somewhere, but I haven't found them yet. One particularly useful table is "FunctionKeyNames". Here, you'll find many keystroke reference strings.

App Kit Calls

The _NXKitString mechanism is used widely in AppKit when displaying localized strings

Color Conversions are a hot topic and an oft-repeated plea amongst novice Cocoa developers is a way of converting from an NSColor to a CGColorRef. At least, if you Google for it, you'll see this question popping up everywhere.

It turns out that converting an NSColor object to the equivalent CGColorRef is deliciously simple - if you're in the know. I found an internal AppKit routine that pretty much does this job for you. Unfortunately, you can't call it directly from Cocoa-land because it's not a public symbol exported by the AppKit framework. However, what the routine does is very straightforward: it works by calling an undocumented method on the NSColor class.

If you were to come up with an equivalent routine of your own, it might look something like this:

CGColorRef CGColorFromNSColor (NSColor * color)
{
        CGColorRef result = nil;
        if ([color respondsToSelector: @selector (_createCGColorWithAlpha:)])           result = [color _createCGColorWithAlpha: [color alphaComponent]];
        return result;
}

As you can see, this code is very straightforward: we just check the presence of the undocumented selector, returning nil if the passed-in NSColor instance doesn't respond to it. In order to prevent the compiler from generating warnings, you'll also need to convince it that NSColor responds to the undocumented selector, providing an interface declaration like this:

@interface NSColor()
- (CGColorRef) _createCGColorWithAlpha: (float) alpha;
@end

You might wonder why the respondsToSelector: check is necessary? Well, for starters, it's wise to build such checks into your code when using undocumented routines. Also, it just so happens that NSColor is an example of a class cluster. In case you're unfamiliar with this term, a class cluster is a group of inter-related private classes, all of which descend from a public abstract class, in this case, NSColor.

Other examples of class clusters include NSArray, NSData and NSString. It might surprise you to know that NSColor is an abstract class, but in a real sense it is. For example:

[NSColor blueColor];                    // returns NSCachedRGBColor
[NSColor _blueControlTintColor];                // returns NSCachedDeviceRGBColor
[NSColor toolTipColor]                  // returns NSDynamicSystemColor

The point here is that all the class names mentioned on the right are descendants of NSColor; you will get different descendant classes returned to you depending on what type of color you request.

NSColor does not, itself, implement _createCGColorWithAlpha: which is one of the reasons it's, in effect, an abstract class. As far as I can see, all the descendant classes do implement it - but please don't quote me! ®

Secure remote control for conventional and virtual desktops

More from The Register

next story
BBC: We're going to slip CODING into kids' TV
Pureed-carrot-in-ice cream C++ surprise
China: You, Microsoft. Office-Windows 'compatibility'. You have 20 days to explain
Told to cough up more details as antitrust probe goes deeper
Linux turns 23 and Linus Torvalds celebrates as only he can
No, not with swearing, but by controlling the release cycle
Scratched PC-dispatch patch patched, hatched in batch rematch
Windows security update fixed after triggering blue screens (and screams) of death
This is how I set about making a fortune with my own startup
Would you leave your well-paid job to chase your dream?
prev story

Whitepapers

Endpoint data privacy in the cloud is easier than you think
Innovations in encryption and storage resolve issues of data privacy and key requirements for companies to look for in a solution.
Implementing global e-invoicing with guaranteed legal certainty
Explaining the role local tax compliance plays in successful supply chain management and e-business and how leading global brands are addressing this.
Advanced data protection for your virtualized environments
Find a natural fit for optimizing protection for the often resource-constrained data protection process found in virtual environments.
Boost IT visibility and business value
How building a great service catalog relieves pressure points and demonstrates the value of IT service management.
Next gen security for virtualised datacentres
Legacy security solutions are inefficient due to the architectural differences between physical and virtual environments.