[Re-sending this message with new details, and also because my thread was hijacked yesterday.]

In debugging my undo grouping issue, I've replaced NSUndoManager's - beginUndoGrouping and -endUndoGrouping with methods that log whenever they're invoked.

- (void)replacement_beginUndoGrouping {
   NSLog(@"WILL beginUndoGrouping for %@", self) ;    // line 1
   NSInteger oldLevel = [self groupingLevel] ;
   NSInteger localSeqNum = gSeqNum ;
   [self replacement_beginUndoGrouping] ;             // line 4
   NSLog(@" DID beginUndoGrouping level: %d->%d locSeqNum=%d",
         oldLevel, [self groupingLevel], localSeqNum) ;
   gSeqNum++ ;
}

(For those unfamiliar with Method Replacement [1], the above is NOT an infinite loop because [self replacement_beginUndoGrouping] invokes the ORIGINAL (Cocoa's) -beginUndoGrouping.)

Here's a snippet from Xcode's log while performing commands that invoke -beginUndoGrouping:

11:27:57.531 Test[804:10b] WILL beginUndoGrouping for <NSUndoManager: 0x170441d0> 11:27:57.547 Test[804:10b] WILL beginUndoGrouping for <NSUndoManager: 0x170441d0> 11:27:57.555 Test[804:10b] DID beginUndoGrouping level: 0->1 locSeqNum=5 11:27:57.556 Test[804:10b] DID beginUndoGrouping level: 0->2 locSeqNum=5

So, apparently this method is being invoked twice, but the second one starts before the first one is complete! At first I thought that this was just Xcode's console doing some of the lazy logging like Leopard's Console.app which drives me nuts. But the values of locSeqNum=5 and oldLevel=0 and the milliseconds say that these statements really ^are^ executing out of sequence. Single-stepping in the Debugger shows the same thing -- execution jumps from "line 4" back to "line 1". And note that this is all in the main thread, 10b and, yes, the same instance, 0x170441d0.

This only happens about 20% the time. Other times, statements execute as expected. One obvious possibility is that Method Replacement misbehaves and does not invoke the replacement in this repeatable test case. How can this happen?

Jerry

[1] http://developer.apple.com/SampleCode/MethodReplacement/index.html

Here's the entire implementation:

#import <objc/runtime.h>

static NSInteger gSeqNum = 0 ;

@implementation NSUndoManager (Debug20090818)

+ (void)load {
   NSLog(@"%s is replacing methods", __PRETTY_FUNCTION__) ;
   Method originalMethod ;
   Method replacedMethod ;

originalMethod = class_getInstanceMethod(self, @selector(beginUndoGrouping)) ; replacedMethod = class_getInstanceMethod(self, @selector(replacement_beginUndoGrouping)) ;
   method_exchangeImplementations(originalMethod, replacedMethod) ;

originalMethod = class_getInstanceMethod(self, @selector(endUndoGrouping)) ; replacedMethod = class_getInstanceMethod(self, @selector(replacement_endUndoGrouping)) ;
   method_exchangeImplementations(originalMethod, replacedMethod) ;
}


- (void)replacement_beginUndoGrouping {
   NSLog(@"WILL beginUndoGrouping for %@", self) ;
   NSInteger oldLevel = [self groupingLevel] ;
   [self replacement_beginUndoGrouping] ;
NSLog(@" DID beginUndoGrouping level: %d->%d", oldLevel, [self groupingLevel]) ;
}

- (void)replacement_endUndoGrouping {
   NSLog(@"WILL --endUndoGrouping for %@", self) ;
   NSInteger oldLevel = [self groupingLevel] ;
   [self replacement_endUndoGrouping] ;
NSLog(@" DID --endUndoGrouping level: %d->%d", oldLevel, [self groupingLevel]) ;
}

@end
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to