Signal for a class method in ReactiveCocoa - objective-c

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.

Related

Why does registering a subclass with its superclass in +initialize present a chicken and egg issue? (objc)

Just reading an excerpt from this website.
Because +initialize runs lazily, it's obviously not a good place to
put code to register a class that otherwise wouldn't get used. For
example, NSValueTransformer or NSURLProtocol subclasses can't use
+initialize to register themselves with their superclasses, because you set up a chicken-and-egg situation.
I understand that +initialize is run once per class when the first message is sent to that class. Also, if any of the subclasses do not implement their own +initialize, the +initialize method will be run again in the superclass.
I am just not 100% on why registering a subclass with its superclass in its own +initialize method would present a chicken and egg problem.
Is it because the superclass may have never had its +initialize invoked, and you are trying to register your subclass with its superclass in a method that depends on the superclass calling its +initialize first?
Just a little bit of further clarification would go a long way for me, thank you.
Take the example of NSURLProtocol. The way it's used is that registered subclasses are asked, in turn, if they can handle a request. The first to answer yes gets an instance created and the request is handed off.
The initialize method is only called if a message is sent to the class. Since only registered subclasses are asked to handle a request, you can't register in initialize because it won't ever be invoked.
Two extracts from the documentation on the initialize method:
The runtime sends initialize to each class in a program just before the class, or any class that inherits from it, is sent its first message from within the program. The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses.
...
Because initialize is called in a thread-safe manner and the order of initialize being called on different classes is not guaranteed, it’s important to do the minimum amount of work necessary in initialize methods. Specifically, any code that takes locks that might be required by other classes in their initialize methods is liable to lead to deadlocks. Therefore you should not rely on initialize for complex initialization, and should instead limit it to straightforward, class local initialization.
The initialize message is sent to a class the first time the runtime encounters it, for example the first time you need to allocate that class or the first time you access its sharedInstance method (in case of a singleton), and it acquires some locks in order to guarantee the thread safety. If you make references to subclasses from within this method, you can get into a deadlock situation, as both the base class and the subclass will lock onto the same thing.
For example, let's consider the scenario of a superclass MyClass and one of it's children MySubclass:
#interface MyClass
#end
#interface MySubclass: MyClass
#end
#implementation MyClass
+ (void)initialize {
[MySubclass doSomething];
}
When the runtime encounters the first usage of MyClass, it acquires a lock, and calls the class method initialize. Now, when executing the method it realises that this is also the first time it encounters MySubclass, and must also intialize it before the class can do some actual work. And what does this trigger? Yes, you've guessed, another call to +[MyClass initialize].
This how we end up in the chicken-egg situation, or to put it more technical - the deadlock, or the recursion. MyClass calls on MySubclass, this means that MySubclass needs to be initialized before MyClass is used. However MySubclass is a child of MyClass, so MyClass should be initialized first. So, which one the two should be first initialized?

-forwardInvocation for class methods

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:

Class methods and instance methods - when/when not to use them?

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.

Objective C and magic methods in class

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

Objective-C: Class vs Instance Methods?

In Objective-C, while creating any class, how do we decide whether we need to mark a method as Class method or Instance Method ?
I know the difference between the 2, but my question is how to decide the marking (+/-) for any method ?
+ denotes a class method, - denotes an instance method. You create class or instance methods where your application needs them. Should you actually know the difference between the two, and your application, then you should have no problems understanding when to use which.
I believe you don't know the differences in how they apply to your application, so here's a small primer:
You use a class method when you need to access some behaviour globally through all instances of that class. i.e., [[self class] someSpecialThing];
You also use a class method when you need a factory method; and
Everywhere else, you use an instance method.