Re: Cocoa et al as HCI usability problem
Re: Cocoa et al as HCI usability problem
- Subject: Re: Cocoa et al as HCI usability problem
- From: Greg Titus <email@hidden>
- Date: Mon, 19 May 2008 11:21:44 -0700
On May 19, 2008, at 11:00 AM, Peter Duniho wrote:
On May 19, 2008, at 10:48 AM, Greg Titus wrote:
You've translated the Objective-C syntax into C# syntax, but the
point of the question is to think about what
prepareWithInvocationTarget() does. How would you write that method
in C#?
Well, it was a poorly stated question then. His primary
presentation asked how I'd write the code he posted, not the
supporting implementation details.
I agree. It could have been stated a lot better.
In Objective-C, after you call -prepareWithInvocationTarget: on an
NSUndoManager, it then accepts _any_ message call of any kind. It
is completely and totally dynamic. It accepts messages from your
application which weren't defined and didn't exist when the
NSUndoManager class was compiled. The undo manager accepts the
message, saves the target and method invocation with an arbitrary
number of arguments and is able to re-invoke it later on the
original target when the user asks you to Undo.
Thanks. That certainly makes the example more clear, and make more
sense.
That said, because of the existence of reflection in C# and Java,
similar functionality isn't really that difficult in those
languages. It's trivial to take any arbitrary class or instance of
a class and invoke any arbitrary named method with an arbitrary
number of arguments, immediately or later as necessary.
I would agree that in the light you've offered, the NSUndoManager
offers a somewhat more compelling use case than previous examples.
But it's not true that the C# or Java version would be significantly
different. They would be only slightly more verbose (though yes, I
admit...they would be more verbose, albeit slightly).
I've worked in Java quite a bit in the past, and I disagree, but more
to the point: I've never done significant work in C# before, so if
that's an environment you are familiar with and you are willing, I'd
very much like to see what prepareWithInvocationTarget: would look
like in that language.
NSUndoManager's Objective-C implementation looks something like this:
// all we need to do here is save a pointer to the target object in
our instance variables temporarily
- (void)prepareWithInvocationTarget:(id)target
{
_target = target;
}
// this method is a part of the introspection done by the Obj-C
runtime on looking up info on what method to call, if we have a
target, act as if we are that target as far as the runtime is concerned
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
if (_target)
return [_target methodSignatureForSelector:aSelector];
else
[super methodSignatureForSelector:aSelector];
}
// the Obj-C runtime calls this method when it doesn't find a pre-
existing defined method for a selector called upon you. The normal
behavior is to throw an exception. Here we'll just re-direct the
target of the message invocation back to our target, and save the
invocation in a list. Then nil out our temporary target variable.
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
[anInvocation setTarget:_target];
[_undoStack addObject:anInvocation];
_target = nil;
}
// Call invoke on all the NSInvocation objects that we've saved.
They'll perform message calls on all their original targets.
- (void)undo
{
[_undoStack makeObjectsPerformSelector:@selector(invoke)];
}
Now in the real NSUndoManager there is a little more complication
because there are multiple steps of undo supported and so on, but this
is really all the code that you need to support a really powerful and
general concept.
Hope this helps,
- Greg
_______________________________________________
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