How can I tell the compiler that my class resolves methods dynamically? - objective-c

I have a class which uses resolveInstanceMethod to dynamically implement methods.
When I call the dynamically implemented methods from other parts of the code, the compiler emits a warning that the object may not respond to the selector. I would like the compiler to not emit such warnings for this class, but I don't want to suppress warnings when I invoke an invalid selector on other classes. Is this possible?

Assuming you know the method signatures that will be dynamically resolved at compile time, you can declare 'em in an informal category:
#interface MyDynamicallyResolvingClass(MethodsThatWillResolveAtRuntime)
... declare the methods here ...
#end
No need to provide an implementation.
If you don't know the signatures -- if the method names are dynamic, too -- then you'll need to use either -performSelector: (or the single or double object argument variants) or you will likely want to use NSInvocation, unless performance is a major concern (if it is, there are alternative solutions that are significantly more fiddly).

Use performSelector:
It's equivalent to sending a message directly to the receiver, however, it allows you to send messages that aren’t determined until runtime.
If your methods take one or two arguments, you can use the sisters of this method: – performSelector:withObject: and – performSelector:withObject:withObject:
If your methods have more than two arguments, or arguments that are not of object type, this answer is not adapted.

Related

Why would I use an NSInvocation instead of a Block?

Can someone offer a concrete reason for using an NSInvocation instead of just using a Block, or even a regular method call? I am finding descriptions of NSInvocation around the Web, but no examples of where it is vital to use or even the only good option.
NSInvocations and blocks can both be used to encapsulate a method call, along with arguments and a receiver that aren't defined until runtime. Before blocks existed, NSInvocation was the only way to do this. If that's all you need to do, blocks are a better bet. Uses of NSInvocation are quite rare these days.
However, unlike blocks, which can represent any amount of code along with captured values, an NSInvocation always represents a single method call.
This has some advantages:
Unlike blocks, which are opaque, an NSInvocation can be queried for the selector, the receiver, the arguments and the signature of the invoked method. If you receive an NSInvocation as an argument to a method (as with NSObject's -forwardInvocation), you can extract the arguments and call a different method instead.
An NSInvocation can be constructed for an arbitrary method call at runtime using -initWithMethodSignature:. If you wanted to implement an eval() function for Objective-C, for example, you'd use NSInvocation to actually invoke the methods.
NSInvocation allows you to dynamically at runtime construct and invoke an Objective-C message call, to a method that you may not know at compile-time, and it allows you to set the arguments using the information about the types and number of arguments from the signature of the method which again you may not know at runtime. (You may have a place that needs to be able to call different methods with different signatures, and pass different things depending on those signatures.) Thus it adds a level of dynamic-ness to the message passing mechanism. I am not sure how blocks relate to this.
NSInvocation is also used in -forwardInvocation: if you want your object to be able to handle arbitrary (not fixed at compile-time) messages, where the message dispatch system constructs an NSInvocation object describing the call and pass it to you, so that you can introspect and potentially modify the arguments and invoke it on another object or otherwise handle the information. This adds a lot of dynamic-ness in handling of messages at runtime. I also don't know how blocks relate to this.

Is there a way of specifying a selector without the #selector syntax / what is going on behind the scenes with #selector

Is #selector a convenience syntax for some sort of longer C syntax, or is it a "hard wired" part of the Objective-C language/compiler? For example, I know that when I call #property, depending on the arguments, different equivalent Objective-C code is "generated" re: getters and setters. What is going on behind the scenes with #selector? Is it specifying an Objective-C message?
#selector() is a part of the language. It specifies literal SEL just like #"" specifies a literal NSString.
It's worth understanding that #selector represents a selector, not a message. A selector is just a name. It's just one small part of a message. It doesn't even carry type information.
Also note that #property doesn't generate anything. It just promises that the object will respond to one or two selectors (the getter and the setter). There are several ways to fulfill that contract. #synthesize is just one of them. You can also manually implement the needed methods, or use #dynamic to promise that it will somehow be handled at runtime.
To answer the question in your title, NSSelectorFromString will let you create a selector from an NSString (you can also do the opposite with NSStringFromSelector), although it's more efficient to use #selector.

Suppressing Class Method Not Found Warnings in Xcode [duplicate]

This question already has answers here:
Using #pragma to suppress “Instance method not found” warnings in Xcode
(5 answers)
Closed 9 years ago.
I have a class whose methods are determined at runtime, as indicated in my question here. This works great, but now I have a bunch of warnings that look like the following littering my code:
Class method '+objectIsNotNil:' not found (return type defaults to 'id')
While these warnings don't actually affect the build process, they're very annoying and make it harder to spot relevant warnings. Is there some way to disable them, but only for the Assert class (maybe some kind of macro)? If this isn't possible, then is there some way to turn them off for the entire build?
One alternative would be to use performSelector:withObject: instead of the direct method call.
So instead of:
[Assert objectIsNotNil:object];
You could have:
[Assert performSelector:#selector(objectIsNotNil:) withObject:object];
It does not look quite as nice but it will remove the warnings. Furthermore, this pattern will work for any selector you want. To make things look a little better you could use macros in the following way:
#define ASSERT_PRECONDITION(sel, obj) [Assert performSelector:#selector(sel) withObject:obj]
This way your assert would look like this:
ASSERT_PRECONDITION(objectIsNotNil:, object);
these cases should be extremely rare...
I've declared a hidden protocol which declared the methods with proper signatures. 'Hidden' in the sense that it was only included by the translations which needed them.
#protocol MONRuntimeClassInterface
+ (BOOL)objectIsNotNil:(id)object;
#end
Easy answer:
You don't want to do this. And if I understand your problem right, you don't need to. You're defining all the relevant methods in your Predicate class described in the link and Assertion is just forwarding to them. Including Predicate.h and making sure everything's declared in the interface should work fine. Like methods called on objects typed id, the compiler will consider methods called on a Class object to be found so long as it knows of at least one class in that compilation unit that implements a class method with the same name.
Alternative answer:
If you really want to suppress compiler warnings, for example if you're calling a method that don't exist anywhere at compile-time then you need to use either NSObject's performSelector: method or the runtime function objc_msgSend(). This won't be checked for a matching method at compile time. However, for some C types which you could plausibly want to pass as arguments (floats and certain larger structs), the compiler needs to know their type. In the absence of a method definition, it needs information from you. performSelector: works by only accepting objects of type id. objc_msgSend needs casting casted to a function with the appropriate signature before it's called (and in some cases, replacing with a variant function). Mike Ash has a good explanation of how this works here.

Objective-C Find all init (constructor methods)

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.

What is the point of Protocols?

I've been writing various stuff using protocols as per example code, but also using some third party stuff, and they seem to adopt quite different approaches. Some specifically adopt the protocols in the interface using
#interface myClass <myProtocol>
others don't do that at all and merely pass themselves and are then set as delegates, but the end result seems to be exactly the same. I've tried both, and they both work fine. If someone was able to explain this I'd be a happy camper! Thanks very much.
A protocol declares a set of messages that an object must respond to (or with #optional, can respond to). In Objective-C, its only point (almost)* is to allow the compiler to flag up warnings if you pass an object that doesn't implement all the methods of the protocol with the correct signatures.
Taking a simple example: NSMutalbeDictionary has a method -setObject:ForKey: which sets the value for a particular key. The key is declared as type id which means you can pass any object and the compiler will not complain. However, the documentation for the method says:
The key is copied (using copyWithZone:; keys must conform to the NSCopying protocol).
so if you pass an object that doesn't have a -copyWithZone: method, you will get a exception at run time saying the key does not respond to -copyWithZone:. It would have been nice if the compiler could have detected your error.
If Apple had declared the method
-(void)setObject:(id)anObject forKey:(id<NSCopying>)aKey;
the compiler would have known about the requirement for -copyWithZone: (it's the only method declared in NSCopying) and would have caught any instances of passing incompatible objects at compile time. I think the reason they didn't do that is for backward compatibility. If bbum is reading, he might know the real reason why not.
*I say "almost" because you can test to see if an object conforms to a protocol at run time.
Objective-C can do both static and dynamic typing, so that protocols aren’t really required for the usual use cases. You can always type your delegate as id and then send it whatever messages you want. (The compiler will warn you if you attempt to send a message that’s not visible from the current file. That’s about the only sanity check it can do for id-typed objects without doing advanced type inference.)
But narrowing the id type down with protocols is nice and recommended, because 1) the code is more readable, 2) the compiler will warn you if you try to send the delegate some bogus message and 3) you’ll get better code completion.
Also the Xcode Code Sense can be very helpful if you use protocols. Sometimes it will suggest the missing methods.