WebObjects: The Gift that Keeps on Giving

About eleven years ago I became acquainted with Apple WebObjects. WebObjects was in the midst of a transition from Objective-C to Java at the time and I entered the WebObjects picture on the Java side of the equation. The fingerprints of the original Objective-C version of WebObjects were visible throughout the product. You had classes like NSDictionary and NSArray in the foundation package and patterns such as delegation throughout the design. Most/all of these concepts themselves came to WebObjects from NeXTSTEP and OpenStep.

Years later, I entered the world of iOS and Cocoa desktop programming. Much of the learning curve in these technologies was eased due to my prior experience with WebObjects. This is true in spite of the fact that my WebObjects usage involved no Objective-C work at all.  The conceptual cores of iOS and Cocoa share a common heritage with WebObjects.

More recently I had an opportunity to work with the open source object-relational mapping framework called Apache Cayenne. Cayenne was inspired by the Enterprise Objects Framework (EOF) which was part of the WebObjects product. It’s not an exact clone of EOF, but my prior WebObjects experience made me feel right at home with Cayenne. Completing the picture is a recent investigation of Apache Tapestry. Tapestry is a component-oriented web framework also inspired by WebObjects. Working with the component-oriented approach taken with Apache Tapestry felt like going home (albeit to a greatly renovated house.)

So, more than eleven years after first developing with Apple WebObjects, the time investment  that I made in learning/mastering that product is still paying dividends. My hat’s off to all those who have created the line of technologies that both precede and descend from WebObjects.

NSDatePicker misbehavior

NSDatePicker does not behave as it should with respect to keyboard events. Specifically, an NSDatePicker will not handle or forward key events triggered by the Return or Enter key. This becomes an issue if you have a window with a default button. The proper behavior would have the button’s action triggered whenever Return or Enter are pressed.

One possible solution is to subclass NSDatePicker to get the desired behavior in keyDown:.

#define RETURN_KEY_CODE 36
#define ENTER_KEY_CODE 76

@implementation MJTDatePicker

- (void)keyDown:(NSEvent *)theEvent {
	unsigned short keyCode = [theEvent keyCode];
	// forward return key and enter key events to the next responder
	if (keyCode == RETURN_KEY_CODE || keyCode == ENTER_KEY_CODE) {
		[[self nextResponder] keyDown:theEvent];
	} else {
		[super keyDown:theEvent];
	}
}

@end

Here’s a sample project that demonstrates the problem and the solution.

A handy logging macro for Cocoa

When developing software, I tend to use both logging and the debugger to gain insight into application behavior.  When it comes to logging, I wanted a way to embed log statements in my code that wouldn’t impact release builds of my applications.

While there are clones of Log4J out there for Objective-C, I wanted to keep things simple.  What I’ve come up with is a macro that I place in an application’s _prefix.pch file:

#ifdef DEBUG
#define DLog(format, ...) NSLog([@"%s " stringByAppendingString:format], __FUNCTION__, ##__VA_ARGS__)
#else
#define DLog(...)
#endif

Then I place DLog() statements in my code where desired. For example, if I place DLog(“Hello”) in the initialize method of AppController, the output would appear as follows:
2010-05-12 06:21:35.627 AppName[28401:a0f] +[AppController initialize] Hello

Note that the location of the log statement is embedded in the output.  To have the DLog macro enabled for your debug builds, you’ll need to define the DEBUG preprocessor macro in your build settings.

Follow

Get every new post delivered to your Inbox.