質問

This is an intentional "fork" of the question: Obj-C introspection: How can a method reference its own selector?

I need to do the exact same thing as the OP, but whereas he didn't need to pass any arguments, I do.



I have a way already to call a method with multiple unknown arguments (NSInvocation). I have some convenience methods to do this for me, like in this question. However, having to duplicate the effort for each method in each class where this is required has led to maintenance issues, and hellish debugging when the wrong argument was passed (or in the wrong order) to the convenience method.

That itself, is a relative minor issue, but one I've been grappling for two years, and would like to solve. By having a one-line macro (like @Michael57) to call my convenience method, automatically inspecting the selector (using _cmd) and the arguments (using ?) and calling the convenience method as I wished.


Note that this is for methods with fixed argument lists and not variadic. So I'm not sure if the va_args approach will work for inspecting arguments or not.

So both from a code management perspective, and purely out of technical curiosity (if _cmd exists for selectors, there must be something for arguments?) I would like to know how standard Obj-C method arguments can be introspected.


I hope this is something very obvious I'm missing. Thanks for the help!


EDIT: Some sample code: The BASIC purpose of what I'm trying to do is to always run methods called on a certain instance, in a single thread. To do this I have a convenience method like so in an NSObject category:

- (void)performSelectorInBackground:(SEL)aSelector waitUntilDone:(BOOL)waitUntilDone withArgumentLocations:(void *)firstArg,...;

Which runs the called selector on the target object in a specific background thread mapped specifically to that instance. All this is just to avoid some sticky synchronization issues that would otherwise occur.

Maybe all this is kludgy in the first place, but I'm way past that. This code is integrated in too many places. :)

The "withArgumentLocations" variadic arguments list is a list of pointer locations that can take in both scalar values and regular Obj-C objects, thus making the usual task of calling a selector in the background with variable number and type of arguments an easy 1-line affair.


Anyway, an actual use case is as below:


- (void)loginRequestWithUsername:(NSString *)username andPassword:(NSString *)password {

if(![self isInBackgroundThread])
{
    [self performSelectorInBackground:@selector(loginRequestWithUsername:andPassword:) waitUntilDone:NO withArgumentLocations:&username, &password, nil];
    return;
}



[self isInBackgroundThread] is another convenience method which checks if the current execution thread is the "assigned" one for this instance.

So this approach has worked fine for individual method calls, but now I want to expand this to all methods within a class. This has led to issues sometimes when the "argumentLocations" are not substituted properly, or not in the right order, etc leading to hellish debugging.


Which is why I'd like to replace the above block of code with a little macro, which I can simply paste in every method to achieve what I need.


Which is why this macro should be able to query its own selector (_cmd) and the arguments (using ?) and pass these along to my performSelectorInBackground:waitUntilDone:withArgumentLocations: method.

役に立ちましたか?

解決

The first thing that comes to mind about getting an NSInvocation is you could not implement the method, and then -forwardInvocation: would be called with the properly constructed NSInvocation. But I guess that is not directly helpful since you need to implement the method and do stuff in the method. However, perhaps what you could do in -forwardInvocation: is invoke the invocation on another object ("forwarding the invocation"), where the method on that object does the real stuff. Then you could also store the invocation in some place that that method can access if necessary. Or maybe you can do the "re-run" logic you want in -forwardInvocation: itself.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top