Does objective-c offer a way to intercept calls to class method that does not exist?
The forwardInvocation method is what you are going to want to use. It is called automatically when a non-existent selector is called on an object. The default behavior of this method is to call doesNotRecognizeSelector:(which is what outputs debug information to your console), but you can override it do anything you want. One recommended approach by Apple is to have this method forward the method invocation to another object.
- (void)forwardInvocation:(NSInvocation *)anInvocation
Note that forwardInvocation is a fairly expensive operation. An NSInvocation object needs to be created by the framework and (optionally) used to invoke a selector on another instance. If you are looking for a (relatively) faster method of detecting non-existent selectors then you can choose to implement forwardingTargetForSelector instead.
- (id)forwardingTargetForSelector:(SEL)aSelector
You should Apple's documentation for how to override these methods effectively, there are some gotcha's to watch out for, particularly when overriding the forwardInvocation method on the same object that will have the missing selectors.
Yes, you can with the resolveClassMethod: class method (which is defined on NSObject):
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html
Here is also something to watch out for (stumped me the first time): http://iphonedevelopment.blogspot.com/2008/08/dynamically-adding-class-objects.html
Related
I was using method swizzling to wrap all method invocations in a class with some extra functionality. Specifically I was:
Checking if the required object for this method call was in the cache
If the cache had that object return it.
If not, dispatch to the original implementation, populate the cache and return that.
For each method, I would reroute to an advised method. And implement the new method using + (BOOL)resolveInstanceMethod:(SEL)sel and IMP_implementationWithBlock.
It worked fine, but the code didn't read nicely. It seems NSProxy will provide a neater way to implement this functionality.
But still another alternative, would be to simply have an NSObject subclass stand-in and intercept method calls around my target object's methods. By overriding forwardInvocation and methodSignatureForSelector, I can get the required outcome.
So what does NSProxy give me? Why should I use this instead?
The point of NSProxy is that it doesn't implement most methods. That's necessary to be sure that the Objective-C forwarding machinery gets invoked to begin with. If you start with NSObject, there are a lot of methods which will just be directly dispatched without you having an opportunity to forward them.
using the "Method * class_copyMethodList(Class cls, unsigned int *outCount)" function one can get a list of all methods that exist on an objective-C class.
I would like to know how to find which of these methods are constructors as I am writing an IOC container. I would like to determine the constructors and their parameter types.
I would like to know how to find which of these methods are
constructors as I am writing an IOC container. I would like to
determine the constructors and their parameter types.
In short, you can't. Or, at the least, you'll find that down this path lies madness.
First, Objective-C does not have constructors. It has initializers, sometimes many, and -- for a properly written class -- only one of which is the designated initializer. There is no way to identify the designated initializer at compile time or run time.
How do I use this with a Method * and no instantiated member of the
class?
You don't. First you allocate an instance of the class, then you initialize the instance.
Overall, this level of abstraction just isn't done in Objective-C outside of academic investigations. It can be done, but it is generally avoided because of the fragility of the resulting solution and the hairball of code-hell that is trying to dynamically support the underlying C ABI (go look at the source to libffi).
If you want to go down this path, then you are far better off either defining a custom abstract class that all of your containers will subclass that can provide the binding logic to the class behind it.
Or use protocols; i.e. a class could implement an IOCBean protocol and one method would be initIOCGoop that is the designated initializer goo.
Doing this generically for all classes is going to be rife with fragility, special cases, and will require a gigantic mess of code that will be difficult to maintain over time.
You can get the method signature by using the following method:
methodSignatureForSelector:
From the documentation:
An NSMethodSignature object records type information for the arguments and return value of a method. It is used to forward messages that the receiving object does not respond to—most notably in the case of distributed objects. You typically create an NSMethodSignature object using NSObject’s methodSignatureForSelector: instance method (on Mac OS X v10.5 and later you can also use signatureWithObjCTypes:). It is then used to create an NSInvocation object, which is passed as the argument to a forwardInvocation: message to send the invocation on to whatever other object can handle the message. In the default case, NSObject invokes doesNotRecognizeSelector:, which raises an exception. For distributed objects, the NSInvocation object is encoded using the information in the NSMethodSignature object and sent to the real object represented by the receiver of the message.
I have been reading Apple's "The Objective-C Programming Language", I noticed that if you have say,
Class A /w methods MA and MB, where MA calls MB with "[self MB]".
If you subclass Class A, lets call it SubClass A, and over-ride MB. Made an instance of SubClass A and call MA, it will use the new MB. Now if you call "[super MA]" instead, it will still use the new MB.
Am I correct?
So I was wondering if "self" is the "right" way to go about this, calling other methods in the same instance, or if it's only used for special situations like covering initializers.
Yes, self is the right way to send a message to the same instance that the method is executing on.
One of the big things to keep in mind about the object model of languages like Objective-C is that, conceptually, you are not "calling methods" — you're sending messages. You're telling the object what to do, not how to do it. You shouldn't normally have to think about what precise method will execute when you send a message — the object is expected to respond appropriately. So if somebody has overridden this "MB" method, presumably the new behavior is how he wants the object to respond when it gets an "MB" message. If somebody has overridden "MB" such that it is no longer usable the way the old method was, then that sounds like a bug.
Yes it is.
Using self inside your class is the right way to go if you want to call methods that are in the same class.
'self' represents the current instance of the class where you are using it.
self is the right way to go. Every method in Objective-C can be thought of as "virtual" (in C++ parlance).
In SubClass A, you don't need to make an instance, you can access any function of subClass A by sing self.
making new object makes a new instance, so it reintialize all the property for that instance.
so you can't do any thing right with this.
self always be right for accessing same class methods and property.
Hope now you can understand why self rather than making other new instance.
And [super MA] must call method of class A's MA method, no case in which MB calls for calling MA.
I have test it, there is no bug all OOPs concept follow in objective c you can call super class method by calling method on super keyword.
So Probably you are doing some thing wrong. just check it.
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)
Does a method which I check for with respondsToSelector have to actually exist?
What if I only define it in the interface part and fail to implement it? I'm looking at a poor-man's virtual function in Objective-C.
First, yes the method actually has to exist for the check to succeed in the context you describe. respondsToSelector: will return NO if the method is not implemented.
More importantly, I think you mean a poor man's pure virtual function in Objective-C. All instance methods are "virtual" in Objective-C; since method lookup is done a run-time, the subclass' implementation will always be used, even from a pointer of the superclass type. In Objective-C, there is no such thing as a pure virtual base class. You can often achieve what you want by either using a #protocol to define an API or using a base class that provides an implementation that throws an NSNotImplementedException as its body. Subclasses would obviously have to override the implementation, making it effectively pure virtual.
Given that calling respondsToSelector: only makes sense when you don’t know whether a method exists, it’s not entirely clear what you mean.
If you mean, does some implementation of a method with the specified selector have to exist somewhere, the answer is no. Selectors merely represent names of methods. The #selector directive doesn’t reference any aspect of any method implementation.
respondsToSelector will return NO, since the selector isn't callable at run-time. The interface part only affects compilation.