0

I'm having a problem with respondsToSelector with NSMutableSet.

I have a program like this:

NSArray *arguments = [[NSProcessInfo processInfo] arguments];
theClass = [arguments objectAtIndex: 1];
theMethod = [arguments objectAtIndex: 2];
theArgument = [arguments objectAtIndex: 3];

id object = [[NSClassFromString(theClass) init] autorelease];

if([object respondsToSelector:NSSelectorFromString(theMethod)]) {
    NSLog(@"Result: %@",
    [object performSelector:NSSelectorFromString(theMethod) withObject: theArgument]);
} else {
    NSLog(@"Class %@ doesn't respond to %@.",
    theClass, theMethod);
}

I call it using ./program NSMutableSet addObject: str, but the program always says that NSMutableSet doesn't respond to addObject:.

I don't know why respondsToSelector always says that NSMutableSet doesn't respond to addObject. It's the same with ./program NSMutableSet allObjects.

Lucas Kreutz
  • 369
  • 2
  • 4
  • 12
  • 3
    `[NSClassFromString(theClass) init]` should be `[[NSClassFromString(theClass) alloc] init]`... –  Jun 02 '13 at 20:46
  • 1
    do you **know** why this is needed (i. e. it was a typo) or did you think that `[NSClassFromString(theClass) init]` is fine? –  Jun 02 '13 at 20:56
  • I think the problem is that without alloc, it's not allocating memory to the instance. I'm learning Objective-C, I was confused with autorelease. – Lucas Kreutz Jun 02 '13 at 21:34
  • 1
    @LucasKreutz: "I think the problem is that without alloc, it's not allocating memory to the instance." It's more complicated than that. `NSClassFromString(theClass)` returns a class object. What does calling `init` on a class object do? Class objects respond to all the instance methods of its root class (in this case `NSObject`). `-[NSObject init]` essentially does nothing and returns the object it is called on. So what is actually happening is that `object` points to the class object for `NSMutableSet`, not an instance of it. – newacct Jun 03 '13 at 09:34

1 Answers1

2

You were checking something completely different...

[NSClassFromString(theClass) init]

needs to be

[[NSClassFromString(theClass) alloc] init]

instead.

  • I understand the error, but, why didn't the compiler warned me? – Lucas Kreutz Jun 02 '13 at 21:35
  • @LucasKreutz Since `NSClassFromString` returns `Class`, which is the generic Objective-C class type, the compiler has no way or knowing which messages it responds to. –  Jun 02 '13 at 21:40
  • @LucasKreutz: "why didn't the compiler warned me?" Warn you about which part? Calling `addObject:` on `object`? 1) Since `object` is type `id`, the compiler will never warn you on messages you send to it, and 2) You are calling it dynamically using `performSelector:` anyway, so there couldn't be a way to check that at compile-time. – newacct Jun 03 '13 at 09:29
  • @newacct warn that I used init without alloc. Is it possible to call a method in a non allocated object? – Lucas Kreutz Jun 03 '13 at 19:04
  • @LucasKreutz In this case, you were not calling `init` on a "non-allocated instance" of `theClass` (whatever that would mean), but **on the class itself.** And while you can call methods on a class, they don't implement the methods of their instances. For example, the `NSObject` **class** does not respond to `-init`, **instances** of it do. –  Jun 03 '13 at 19:06
  • @H2CO3: "the NSObject class does not respond to -init" Well, yes it does. Class objects respond to all the instance methods of its root class; in this case, `NSObject`, which includes `init` – newacct Jun 03 '13 at 22:47
  • @newacct Oh, right. I stand corrected - it was late yesterday, I've forgotten about metaclasses, whatever. Of course it does (still it returns the class object, and that's what the the confusion arises from). –  Jun 04 '13 at 04:58
  • hmmm, Thank you two. Now it's really clear. I'm programming a project with C++ and another with Objective-c, all this pointers and allocation confused me. Thank you. – Lucas Kreutz Jun 04 '13 at 21:30