I'm struggling to forward a class method through a facade class.
To clarify, I'm overriding all the following methods:
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
-(void)forwardInvocation:(NSInvocation *)anInvocation
+(BOOL)instancesRespondToSelector:(SEL)aSelector
+(NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector
+(IMP)instanceMethodForSelector:(SEL)aSelector
+(BOOL)resolveClassMethod:(SEL)sel
+(BOOL)resolveInstanceMethod:(SEL)sel
.. and yet, for the class method, the only one to be called is +resolveClassMethod. From there, I immediately get an unrecognized selector exception regardless of whether I return YES or NO.
What's going on?
Does class message forwarding work differently to instance message forwarding?
Similarly, why isn't there a +forwardInvocation class method?
Any help would be greatly appreciated.
So you already know that to make an object do forwardInvocation for instance methods, you have to implement the instance methods -forwardInvocation: and -methodSignatureForSelector: (the others are unnecessary). Well, class methods are just methods on the class object. Classes are objects and work like any other objects, and support all the instance methods of the root class (NSObject in this case).
The Objective-C runtime doesn't care that an object is a class object or non-class object. The message forwarding mechanism is the same. So when you send a message to an object, whatever it is, and it can't find it, it just looks for the forwardInvocation: and methodSignatureForSelector: methods on the object. So you need to have these methods on your class object.
i.e. implement the class methods +forwardInvocation: and +methodSignatureForSelector:
Related
We always make singleton object through Class method.What will happened if i make that method instance(use - instead of +) and call that method through a nil object or simply through an object?
Conceptually a the instance method is not attached to any specific instance of a class.
This means that from a design point of view it doesn't make sense to invoke it on an existing object. It's like requiring that a +(int) sum:(int)a with:(int)b should be an instance method when it doesn't need to know anything about an object.
In addition usually a singleton class constructor shouldn't be accessible from clients, if you need to instantiate one to call -instance on it this would defeat the purpose.
Last thing, a singleton should be the only possible instance of an object, if you need to have one to instantiate one then you are in a deadlock: you need an instance to create an instance but you are no allowed to have more than an instance.
Regarding calling it on nil object, if I remember correctly a pointer returned from a message sent to nil will always be nil too.
I'd like to create a RACSignal whenever particular class methods are called. This is easy to do for instance methods (rac_signalForSelector) but I can't find a way to do it with class methods. e.g. I'd like to receive a signal on NSError's errorWithDomain:code:userInfo: and see what parameters it was created with. But really it should be a general solution so I can see when any class method is called. Access to the resulting instance is optional.
Is there a way to indicate to the compiler that a class object conforms to a protocol?
As I understand, by creating +(void)foo class methods, an instance of that class object will have those methods as instance methods. So, as long as I create +(void)foo methods for all required protocol methods, I can have a class object act as a delegate.
My problem of course is that in the class's header file, I only know how to indicate that instances of the class conform to the protocol (as is typically the case). So, the best I've figured out is to cast the class object like so:
something.delegate = (id<SomethingDelegate>)[self class]
Any ideas?
Related, but different:
ObjC: is there such a thing as a "class protocol"?
What you're doing now is correct as it will silence warnings which is your goal. You will be sending the class object messages defined in the protocol for instances which is a bit confusing, but the runtime doesn't care.
Think about it this way: you want to set a delegate to an object that responds to the messages defined in the protocol. Your class does this, and your class is also an object. Therefore, you should treat your class like an object that conforms to that protocol. Therefore, what you've written is completely correct (based on what you're trying to do).
One thing to note, though, is this class will not properly respond to conformsToProtocol:. This is generally okay for a delegate setup anyway (delegates don't usually check if the class conforms — they just check if it can respond to a selector).
As a side note, one thing you can do syntactically is:
Class<SomethingDelegate> variable = (Class<SomethingDelegate>)[self class];
The difference here is that the compiler will use the class methods from the protocol instead of instance messages. This is not what you want in your case, though.
There is no Objective-C syntax to indicate that a metaclass conforms to a protocol.
I think you can do it at runtime, by using class_addProtocol on the metaclass. But I haven't tried it.
I guess you could also write a +conformsToProtocol: method on your class, and lie about your conformance. This could have unexpected side-effects, since there's already a +conformsToProtocol: on NSObject (in addition to -conformsToProtocol:).
Neither of these will eliminate the need for a cast to shut the compiler up. Just use a singleton.
I was wondering when and when not to use class methods and instance methods. I need some practical examples. I am really confused. Another question: can't we do exactly the same things with instance methods that we can with class methods?
Class methods: The method isn't tied to any specific object. In a way it acts like a free function in the class's namespace. No 'self' pointer. For instance [UIScreen mainScreen] is a class method because there's only one screen and there's no need to care about multiple 'screen instances'.
Instance method: Tied to a specific object.
This applies to most OO languages, not just obj-C.
At the implementation level, an instance method call contains a hidden pointer to a data structure (the object), a class method does not.
The practical question to ask is whether your call requires sending the call some specific data which is or could best be encapsulated as instance data inside an object, or not.
You (usually) can do the same thing with class methods as instance methods, but then you have to explicitly pass the object as a visible parameter in the call, which is uglier looking and also potentially disables some method override features of the Objective C language.
Use class methods for utility functions and Instance methods for object oriented stuff.
Eg. For Mathematical calculation (eg sin x ) use class method. But for invoking a behavior specific to an object.. use instance method ..
A class method as the name implies is bounded to the class. You can invoke them just with the name of the particular class. These can be normally exposed methods of a class.
For example
NSArray
+ (id)arrayWithArray:(NSArray *)array;.
You call it with the class name NSArray. What you expect is just a creation of a object of the type of that particular class. This doesn't need an object to invoke. Also these are very basic method required so its better to make it as a class method.
On the other hand instance method as the name implies is very much bound to the instance. Object is an entity that encapsulates state (ivars) and behaviors (methods) of a class. This can be very specific to the object.
For example
- (NSUInteger)count;
Lets take NSArray *a and NSArray *b. If a contains 5 items whereas b contains 4, instance methods called upon these instances will produce different results. And thats why we need instances to be initialized while invoking instance method. They work on the context(or state) of the object they are been called upon. Also they are not exposed as the class methods are.
Hope this helps.
If you want to use instance objet or instance variable you have to go with instance Methods.
Bcz Inside the class you cant access the Instance instance objet or instance variable.
Class methods are static methods.
I need to call a method through the object created by the interface ie
id<MyProtocol>obj;
Now i have created this obj in my main class where i am not implementing the methods of this protocol but i need to access the method which is already implemented in someother class.I am now calling the method as follows
[obj load];
in my main class in the applicationDidFinishLaunching, but i not able to access the method?
Pls do suggest me the correct way of calling the methods through protocols...
A protocol implements nothing. It only describes a set of messages that the object should respond to. Your obj object belongs to some class. This class needs to implement methods described in MyProtocol.
Edit
A protocol is not implemented by a specific class. Any class that claims to conform to a protocol must implement its methods. Any object that claims to conform to a protocol must belong to a class that implements its methods.
In your case, obj is a ClassB, so ClassB must implement methods described by MyProtocol, either directly or through inheritance.
[obj load] is OK. If you want to shut up the compiler you can cast it to id:
[(id)obj load];
But if you know you'll need to call the -load method, maybe you should add the -load method to the protocol, or make another protocol that has the -load method e.g.
#protocol Loadable
-(void)load;
#end
...
id<MyProtocol, Loadable> obj;