CocoaDev

Edit AllPages

Related Links: AspectCocoa, AspectCocoaDocumentation, AdviceProtection, AspectCocoaBugs, ProgrammingByContract, EiffelProgrammingLanguage


Invariance checking is defining a set of conditions that must be true for a class… we check this by implementing -invariant and +invariant for any given class, and loading the class in main before we run the application. Here’s what you would do to use this in your project:

//main.m #import <Cocoa/Cocoa.h> #import “ACInvariance.h”

int main(int argc, const char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

// change InvariantObject to the name of the class you want to have invariant checking
// call it multiple times to load for multiple classes
// InvariantObject should have a -invariant method and a +invariant method defined
[ACInvariance loadAspectForClass:@"InvariantObject"];

    int result = NSApplicationMain(argc, argv);

[pool release];

return result; }

Here’s the class itself

//ACInvariance.h #import <Cocoa/Cocoa.h> #import <AspectCocoa/AspectCocoa.h>

@interface ACInvariance : NSObject {} // No instance vars +(void)loadAspectForClass:(NSString)aClass; -(void)before:(ACInvocation)invocation; -(void)after:(ACInvocation*)invocation; @end


//ACInvariance.m #import “ACInvariance.h”

@implementation ACInvariance +(void)loadAspectForClass:(NSString*)aClass {

id allClasses = [ACPointCut enumerateClassesNamed:aClass,nil];
id eachClass, resultClasses;
resultClasses = [[NSMutableArray alloc] init];
while( eachClass = [allClasses nextObject] ) {
	if( class_getInstanceMethod([eachClass getClass],@selector(invariant)) != NULL){
		id allMethods = [eachClass methodEnumerator];
		id eachMethod;
		while(eachMethod = [allMethods nextObject]) {
			if( ! eachMethod methodName] hasPrefix:@"init"] && 
				! [[eachMethod methodName] hasPrefix:@"alloc"] &&
				! [[eachMethod methodName] hasPrefix:@"invariant"])
			{
				[eachClass addMethod: eachMethod];
			}
		}
		[resultClasses addObject:eachClass];
	}
}
id pointCut = [[[[ACPointCut alloc] initWithJoinPoints:resultClasses];
ACAspect* invariantAspect = [[ACAspect alloc] 
                     initWithPointCut: pointCut  andAdviceObject: [[ACInvariance alloc]init]];
[invariantAspect load];
[invariantAspect autorelease]; } -(void)before:(ACInvocation*)invocation  { 
invocation target] invariant];  } -(void)after:([[ACInvocation*)invocation  { 
[[invocation target] invariant];  } @end