Question

I have the following problem and could not solve it, perhaps someone knows a trick :)

The main object has to be dynamic, because it could be different ...

Function which should be called:

+ (NSArray *)parseJSONString:(NSString *)theJSONString error:(NSError **)errorPointer

As the code already declares, I want to parse JSON. I have several objects which are implementing this function, that's why I use the performSelector method:

if ([[self.theObject class] respondsToSelector:@selector(parseJSONString:error:)]) {
     NSError *parsingError = nil;
     self.myObjectsCollection = [[self.theObject class] performSelector:@selector(parseJSONString:)
                                                             withObject:utf8ResponseString
                                                             withObject:parsingError];        
}

utf8ResponseString contains the JSON ...

I already tried the following:

... withObject:&parsingError -> compile error
... withObject:[NSValue valueWithPointer:&parsingError] -> works until the value will be redirect to the parsingError -> Bad Exec

I have searched for a day and not even have a clou on how to solve this - please help...

Thanks and greetings, mathew

Was it helpful?

Solution

The performSelector:... family of methods only take object arguments. You want to pass a pointer to a pointer, which isn't the same thing as an object, so the type system doesn't allow it. Fortunately, you don't need performSelector: here at all. You can just do [[self.theObject class] parseJSONString:utf8ResponseString error:&parsingError].

You only need to use performSelector: when the message you want to send isn't known until runtime. If you're not passing in a variable as the first argument, you probably don't need it.

However, if you did need to do this, what you'd need to do is write a "wrapper" method that takes an object (say, an NSValue) and calls the real method with the non-object type, and you'd call the wrapper instead of the real method with your performSelector:withObject:.

OTHER TIPS

To add to the other answers for completeness, if you really needed to dynamically call a method whose name is only known at runtime (it turns out you didn't need to in this case, but if you did) with non-object arguments, then the proper solutions would be:

  • Use an NSInvocation, or
  • call one of the objc_msgSend... runtime functions directly

Why don't u call directly the method on the class instead? You have already checked that it can respond to the method. So call the method directly.

[[self.theObject class] parseJSONString: nil error: &error].

By the way you can do a simple stategy pattern swap. Even if the object responder are defined at runtime, the message call isn't. Transtype to id if compiler warn you. Because i'm not sure you can assign protocol on class method. (but maybe u can).

You can even embed all your object-parser into proxy parser Class, so that it's defined at compile time.

What is sure, is that you can pass a pointer to pointer object (**erorr) to performSelector:: (because the runtime is not a soothsayer). If you really need, do a simple c function callBack?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top