Prism Aspects to Help with Monobjc Development

Joanna Carter wrote a great article for our wiki about implementing Key-Value Coding and Cocoa Bindings for Monobjc applications, earlier this week.

Key-Value Coding (KVC) and Key-Value Observing (KVO) are based on Objective-C properties, so for something as simple as a one-line property declaration:

property Name: NSString;

quite a bit of plumbing code is normally required to expose this property properly for the Objective-C runtime: attributes are needed on the getter and setter methods (which in turn forces us to implement those, in the first place), and to participate in KVO, notification methods need to be called in the setter as well. The neat little property expands to something like this:

private fName: NSString;public[ObjectiveCMessage("name")]method getName: NSString;partial;[ObjectiveCMessage("setName:")]method setName(value: NSString);partial;

along with manual implementations for the property getter an setter:

method Customer.getName: NSString;beginresult:= fName;end;   method Customer.setName(value: NSString);begin WillChangeValueForKey("name"); fName := value; DidChangeValueForKey("name");end;

UGH-ly, and a nightmare to maintain – especially once you want to add actual custom logic to the setters, or have a lot of properties in the same class.

With the new support for Aspect Oriented Programming (AOP) code-named “Cirrus” that we’re adding to Delphi Prism (Carlo just blogged about that earlier today), i though, why not wrap all of this up in a nice little aspect.

So i grabbed the latest internal Prism build (carlo had just finished integrating “Cirrus” into our builds), and just a a few minutes later, the [ObjectiveCProperty] aspect was born. It works pretty similarly to the plain attributes that Monobjc provides (such as [ObjectiveCMethod] you saw above), and with it, the above properly now looks like this:

[aspect:ObjectiveCProperty]property Name: NSString;

but provides all the functionality of the “long” implementation we saw before. If you look at the generated assembly in Reflector, you’ll see that appropriate [ObjectiveCMethod] attributes have been added to the getter and setter methods (even though we never implemented getter/setters ourselves, in this case), and the calls to WillChangeValueForKey/DidChangeValueForKey are present in the setter, as well.

The aspect will work on any property, regardless of whether it uses shortcut declaration, a local field or manually specified getter/setter code. Just slap the aspect on, and the property is exposed to the Objective-C runtime. Optionally, the aspect can also take a different name to expose the property as (by default, it camel-cases the name, so “Foo” becomes “foo/setFoo”), and a boolean parameter to disable KVO.

And, most importantly, all of this is implemented in user code: anyone could write an aspect like this, even though the aspect accomplishes tasks that previously would have required extensive changes to the compiler!

As Carlo mentioned, “Cirrus” is still in development, and will ship in a future update to Delphi Prism later this year. Don’t quote me on it, but i would expect it to be available in the May release.


marc hoffman

Chief Architect and CEO here at RemObjects Software. Project Manager for Elements and lead developer of Fire, our awesome new development environment for the Mac.