[Workaround] Re: My NSUndoManager subclass is broken on SL - how to fix?
[Workaround] Re: My NSUndoManager subclass is broken on SL - how to fix?
- Subject: [Workaround] Re: My NSUndoManager subclass is broken on SL - how to fix?
- From: Graham Cox <email@hidden>
- Date: Thu, 3 Sep 2009 14:48:48 +1000
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 (email@hidden)
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:
This email sent to email@hidden