How to call methods on an object of type id - ios

when I'm trying to call a method on an object of type id, i get a warning raised (method not found). how i call the method :
Class A *instanceACasted = (ClassA *)idvalue ;
then call the method
[instanceACasted methodCall];
This is one way but i dont know about the class name using id how i call the method

You can use introspection and performSelector:
SEL selector = #selector(yourMethodSignature:);
if ([obj respondsToSelector:selector]) {
[obj performSelector:selector];
}
Apple documentation on how to use introspection.

To get rid of the warning method not found , you must cast/convert your id type object to the proper object type. But in this case you need to know the Class name of id type object.
If you don't know the class name then follow this answer.

The correct answer depends heavily on what you are actually doing. Your code doesn't compile, and your error message "method not found" does not exist in Clang, so I can't tell what is actually happening. Also, your subject contradicts what I might guess from your code (there is no mention of "id" in your code). Here are a few guesses:
You are calling a method that has not been declared
ObjC mostly reads code from top to bottom, and reads each source file (implementation file, .m file, not header) separately, as its own "compilation unit". So if your source file tries to call a method that is not in your file, you'll get an error message like error: no known instance method for selector 'doSomething' or error: no known class method for selector 'doSomething'.
To fix that, you need to #import the header that declares the class/protocol that defines the method you want to call.
You are calling a class method on an instance (object) or an instance method on a class
Class methods start with a +, instance methods with a -. They are totally separate. So if you declare a method with a +, then call it on an object of that type (instead of on myObject.class or the class name), the compiler may warn you about error: no known instance method for selector 'doSomething' resp. error: no known class method for selector 'doSomething'. Here the important part is that it is looking for a class method, even though an instance method exists, and vice versa.
You are calling a method that the given object/class does not have
In that case, you get an exception that bounces you back into the run loop and a log message at runtime. This could mean that your code is expecting a newer OS's version of a class (which has that method) but is running on an older OS (where this method didn't exist yet). In that case, you get a message like unrecognized selector sent to instance 0x7fffdb13cf38 or unrecognized selector sent to class 0x7fffdb13cf38.
To fix that, you can check whether an object responds to a given method by asking it [theObject respondsToSelector: #selector(doSomething)], and only then calling it, otherwise doing something equivalent that doesn't rely on that method. Or you could check if that method is available ahead of time and just hide the button or whatever that needs this on older OSes that way.
Note that, if you had e.g. an NSObject* and you knew that in one special case it could actually be an NSString*, and you use -respondsToSelector: to verify that it implements #selector(characterAtIndex:) in that case, you may still get an error message that NSObject instances do not responds to -characterAtIndex:. In this case, you can turn off that warning by doing:
NSObject* myNSObject = myArray.firstObject;
if( [myNSObject respondsToSelector: #selector(characterAtIndex:)] )
[(NSString*)myNSObject characterAtIndex: 0];
or whatever. You usually never write code like this, though. Checking "what class is my object" is usually an indicator that you built your class hierarchy wrongly, so I only mention that for completeness' sake.
How does 'id' figure into this?
You mention id in your headline, but your example doesn't use it. If you call a method on id, ObjC will let you do anything. All it wants is that somewhere there is a class or instance method declaration for the given method, on any object. In that case, it will only blow up at runtime if you call a method the given object doesn't have.

Related

Difference between selector and SEL and method call [ ]? [duplicate]

What the difference between a method, a selector and a message in Objective-C?
This is a great question.
Selector - a Selector is the name of a method. You're very familiar with these selectors: alloc, init, release, dictionaryWithObjectsAndKeys:, setObject:forKey:, etc. Note that the colon is part of the selector; it's how we identify that this method requires parameters. Also (though it's extremely rare), you can have selectors like this: doFoo:::. This is a method that takes three parameters, and you'd invoke it like [someObject doFoo:arg1 :arg2 :arg3]. There's no requirement that there be letters before each part of the selector components. As I said, this is extremely rare, and you will not find it used in the Cocoa frameworks. You can work with selectors directly in Cocoa. They have the type SEL: SEL aSelector = #selector(doSomething:) or SEL aSelector = NSSelectorFromString(#"doSomething:");
Message - a message is a selector and the arguments you are sending with it. If I say [dictionary setObject:obj forKey:key], then the "message" is the selector setObject:forKey: plus the arguments obj and key. Messages can be encapsulated in an NSInvocation object for later invocation. Messages are sent to a receiver. (ie, the object that "receives" the message).
Method - a method is a combination of a selector and an implementation (and accompanying metadata). The "implementation" is the actual block of code; it's a function pointer (an IMP). An actual method can be retrieved internally using a Method struct (retrievable from the runtime).
Some other related things that you didn't ask for:
Method Signature - a method signature represents the data types returned by and accepted by a method. They can be represented at runtime via an NSMethodSignature and (in some cases) a raw char*.
Implementation - the actual executable code of a method. Its type at runtime is an IMP, and it's really just a function pointer. iOS 4.3 includes a new ability to turn a block into an IMP. This is really cool.
One of the fun things to realize is that the name of a method (the selector) is distinct from the implementation of the method (the IMP). This means that you can swap them around, if you're feeling daring. You can also add and remove methods at runtime, because all you're doing is editing an entry in a hash table: the key is the selector, and the value is the IMP of the method. This allows you to do some really crazy and trippy stuff. It's not for the faint of heart. :)
A method is the implementation which is run when an object or class is asked to perform some action. It is in the scope of its containing class and is therefore different when referenced through some other class. A selector is an identifier which represents the name of a method. It is not related to any specific class or method, and can be used to describe a method of any class, whether it is a class or instance method.
Simply, a selector is like a key in a dictionary. It can tell you what method someone is talking about, but only if you also have the dictionary itself (the class or object). The method is what you get when you ask for the value from the dictionary using the selector as a key.
This site has a good overview of all the terminology in question: http://www.otierney.net/objective-c.html
Check out the link, but I'll give a quick summary:
A method is essentially like a method of function that you are used to in your favourite programming language.
A message (from the article) "A message can be dynamically forwarded to another object. Calling a message on an object in Objective-C doesn't mean that the object implements that message, just that it knows how to respond to it somehow via directly implementing it or forwarding the message to an object that does know how to."
Selectors can mean two things. It can refer to the name of a method, or "refers to the unique identifier that replaces the name when the source code is compiled. Compiled selectors are of type SEL." (from: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocSelectors.html)

Custom init from from NSClassFromString

I try to dynamically call certain viewController/Feature depends on his Name.NSClassFromString
(that kind of idea was suggested by Facebook).
For Instance from my server I can define in IOS app which feature or viewController should be used.(or On/Off them)
I searched all over Stack but still cant find an elegant way to implement what I want
Class myclass = NSClassFromString(className);
id obj = [[myclass alloc] init];
will work.
But I would like to call my custom init.
Class myclass = NSClassFromString(className);
id obj = [[myclass alloc] initWithCostumInitializer:userInfo];
I cant find a proper way to do it. Of course every time I receive an error because initWithCostumInitializer is not recognised.So I need to make the decision in run time.I believe I missing something.
Tnx a lot.
First off, you shouldn't get a compile-time error about an unknown method if the headers for the possible classe(s) are imported into the .m file where this code is running. Because of exactly this sort of dynamism, ObjC should let you get away with calling fairly arbitrary methods on objects of type id.
But that's just a bandaid solution. Really, if you know that that custom initializer method is present, then it's not an arbitrary class, right? You have some idea what kind of object it is, or at least what kind of base class it derives from, otherwise you wouldn't know to call that method. So you could always:
id customObj = [((BaseViewController *)[myclass alloc]) initWithCustumInitializer:userInfo];
If your error is a runtime error about the receiver missing that selector, then you have a real problem, which is: why are you calling a named method on an object that might not be the kind of object that has that method? If that's what's happening, you'll need to look at the class first to figure out what kind of thing you're actually about to create, and then behave appropriately for the init.

ARC and sending messages to objects without specifying the class at compile time

I'm trying to understand where ARC is getting the method signature information to do its job.
In the following code, I send a message to the parent of this object without specifying its class.
If I don't typecast the parent ivar, the compiler issues a warning.
If I typecast it to id, then the program works and no warnings are issued. The same is true
if I use performSelector:withObject:
If the method on the parent is different to userSelected: then the only thing that works
is performSelector (while issuing a warning).
As I understand it, ARC is getting the method signature from the object the call to self.parent is made. Is this correct? Can you avoid telling ARC what class an object is if the method signature exists in the object from which the message is being sent?
- (void)userSelected:(id)sender
{
if ([self.parent respondsToSelector:#selector(userSelected:)]) {
//1: This fails with error (no visible interface).
[self.parent userSelected:self];
//2: This line works without warnings.
[(id)self.parent userSelected:self];
//3: This line also works
[self.parent performSelector:#selector(userSelected:)
withObject:self];
}
Wil Shipley is correct in his deleted answer when saying that this is not ARC related.
The warning you are getting is about the static type of the receiver (self.parent) and the compiler trying to help you to prevent sending messages to an object that doesn't respond to this selector. In other words: self.parent's class does not contain a declaration of userSelected:.
But the compiler does know a method named userSelected: (in some other class or category) because it lets you send this message to an object without static type information. It's a little like the C language lets you use a void pointer for any type of pointer.
So, again, all of that is not ARC related and would not change when switching to MRC.
Edit:
Yes, when sending messages to id the compiler considers any visible #interface and #protocol to find the selector's declaration. "Visible" in this case means any imported header, be it custom, framework or prefix. The method declaration is needed mainly to get type information of the parameters.
Note that ARC behavior is only affected in very rare scenarios (when the declaration includes information about ownership semantics, like objc_method_family and similar).
If the compiler finds conflicting declarations it emits an error. When trying to compile ...
[(id)nil type];
... you'll get ...
> error: multiple methods named 'type' found with mismatched result, parameter type or attributes
... plus a couple of differing declarations in UIKit, Foundation and other frameworks.

what does do method class in objective c

This might be a silly question. I'm learning objective C (iOS) by studying the code and I came across the expression
[InstanceName class];
What does it do?
I tried to search for class method but It just pops up difference between class method and instance method etc. I guess it might give some sort of class object but I have no idea what is the purpose of the statement.
the original code is Sample Facebook App (scrumptious) using FB SDK....
If you see something like this as a standalone expression....
[InstanceName class];
... then the code is most likely forcing the execution of the +initialize method on said class. The first time any method is invoked on a class, the +initialize method will be invoked prior by the runtime. So, have a look at InstanceName and see if it has a +initialize method.
Note that forcing +initialize to execute in this fashion is a sure sign of bad design. +initialize should never need to be forced like this and should not have execution order dependencies.
There is a legitimate additional reason why this line of code might exist. By referring to InstanceName with a hard reference, it'll force the linker to link in all symbols in the library. (If you don't have a hard reference to at least one symbol in a library -- a .a -- some linkers will simply drop the library from the link unit entirely.)
It gets the class of the object.
So for instance if InstanceName is an instance of class Foo
[InstanceName class]; will return Foo, in a variable of type Class
You can use class_getClassName to get an NSString from this class to log it.
class is a method inherited from NSObject. It lets you get the instance of the class object representing the class of the instance on which the method is called.
It can be used to examine the metadata of the current object. For example, you can use class method to determine if a given object is of a particular class:
if ([sender isKindOfClass:[UIButton class]]) {
...
}
It returns the class of the object. Suppose you have an array of UIView subclasses you created and you want to perform some action only to those who belong to a certain class. You could loop through the array and check for each object's class:
for (id view in myViews) {
if ([view isKindOfClass:[MyUIViewSubclass class]]) {
// Do something
}
}

Why doesn't Xcode complain about undeclared methods when using #selector?

Why are warnings generated when calling methods undeclared in a class interface using conventional means, but not when calling methods using #selector? Is it because selectors can be executed by a different caller than self?
For example:
-(void) doStuff
{
[self doNow]; // Warning: instance method not found
SEL sel = #selector(doNow); // no warnings
}
-(void) doNow {} // this method is not declared in the interface
The "Undeclared Selector" warning is turned off by default. I don't know why. You can turn it back on in the Build Settings.
The documentation for this settings reads:
Warn if a "#selector(...)" expression referring to an undeclared selector is found. A selector is considered undeclared if no method with that name has been declared before the "#selector(...)" expression, either explicitly in an #interface or #protocol declaration, or implicitly in an #implementation section. This option always performs its checks as soon as a "#selector(...)" expression is found, while -Wselector only performs its checks in the final stage of compilation. This also enforces the coding style convention that methods and selectors must be declared before being used. [GCC_WARN_UNDECLARED_SELECTOR, -Wundeclared-selector]
A similar question was asked on SO a few weeks ago.
This is basically because selectors are late-bound. They're not looked up until runtime. There are options for forcing verification during compilation. The question I linked to has some more information on how you can do that.
The way #selector works by default is you are telling the compiler; trust me I have this method somewhere in my class. Its the same concept if you do #class yourclassname instead of importing the .h file which contains the class.
This is because the compiler needs to know the signature of the method in order to call it (i.e. [self doNow];), because such a call translates to either a call to objc_msgSend or objc_msgSend_stret depending on whether the method signature has a return type of a struct or not. (Remember the difference between the selector (simply the name with the colons in it, but with no types) and the signature (the types) of a method.) So it needs to warn because it could be calling the wrong function if it doesn't know.
However, just getting a selector (#selector(...)), it doesn't need to know the types. The selector is simply a name, and you've provided the name. It's all about what you use the selector for. If you use it in performSelector:, it also doesn't need to know the types, because that method only works for methods with argument and return types of objects, so there is no ambiguity. Hence there is no need for a warning.

Resources