For anyone interested (doesn't seem like anyone is, unfortunately) I have worked out a solution which can only be described as an inglorious hack. I have submitted a bug report requesting that NSUndoManager is made (optionally) backwards compatible with earlier subclasses of it. Bug# 7193398.

The workaround is to override NSUndoManager methods as follows:

- (id)  prepareWithInvocationTarget:(id)target
{
        _target = target; //_target is an ivar, non retained
        return self;
}


- (void) forwardInvocation:(NSInvocation*) invocation
{
        [invocation setTarget:_target];
        [invocation retainArguments];
[self registerUndoWithTarget:self selector:@selector (unwrapEmbeddedInvocation:) object:invocation];
}


- (NSMethodSignature *) methodSignatureForSelector:(SEL) aSelector
{
        NSMethodSignature* sig = [super methodSignatureForSelector:aSelector];
        
        if( sig == nil )
                sig = [_target methodSignatureForSelector:aSelector];
        
        return sig;
}


- (BOOL)                respondsToSelector:(SEL) aSelector
{
return [super respondsToSelector:aSelector] || [_target respondsToSelector:aSelector];
}


- (void)                unwrapEmbeddedInvocation:(NSInvocation*) invocation
{
        [invocation invoke];
}

These methods restore 10.5 compatible behaviour, I believe, though I'm not quite certain about the set up of the invocation with respect to retaining its target. Notes for NSUndoManager say it does not retain its targets, but does retain its arguments, whereas notes for NSInvocation state that -retainArguments also retains the target. So I'm not quite sure how to reconcile that (and whether as a result I have a leak through over-retention of the invocation's target).

With the above, you can then override registerUndoWithTarget:selector:object: to implement task coalescing or whatever you wanted to subclass NSUndoManager to do in the first place, and it still works on 10.6 when tasks are submitted via - prepareWithInvocationTarget:

--Graham



On 03/09/2009, at 12:31 AM, Graham Cox wrote:

My app subclasses NSUndoManager, so that it can provide a couple of extra things to the app, namely, task coalescing and a change count that I track to see if certain operations which come from a wide variety of places actually submitted an undo task (and hence the undo manager itself is the one central place that knows about them).

On 10.6, While Undo is still generally working, the stuff my class added are not. In trying to track this down, I was getting some very puzzling results, like none of my breakpoints were firing in my subclass's override for -forwardInvocation. Then I spot this note in the docs:

"On Mac OS X v10.6 and later, this method (- prepareWithInvocationTarget:) returns a proxy object for the receiver that forwards all messages to the receiver as undo operations."

OK, I understand why that was done, but how can I alter my code so it works for this non-backwards-compatible situation? It seems this mysterious proxy object is forwarding to some private method of NSUndoManager that I can't override, so it's bypassing my very useful additions. I need to know where I can hook into whatever this proxy object delivers the task to the U/M.

Any ideas?

_______________________________________________

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