If I override a class method, is there a way I can call the original method (the one that was overridden)? - iphone

In Objective-C, if I override a class method using a category, is there a way I can call the original method (the one that was overridden)?

I present you with three icky ways to do this in +(void)load. In every case, name your method MyCategory_method or so.
class_getMethodImplementation() and class_replaceMethod(). Store the old IMP, and call it directly. You need to get the method's type encoding. Note that you can just use a normal C function too...
class_getInstanceMethod(), method_getImplementation(), method_setImplementation(). As above, but you don't need to get the method's type encoding.
class_getInstanceMethod() on both methods, and then method_exchangeImplementations(). Call MyCategory_method to get the original implementation. This is the easiest way to do it.
Sometimes, it's the only reasonably easy way to make it do what you want...
EDIT: And only do this if you know what you're doing!

http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocCategories.html
Doesn't look like it is possible.
When a category overrides an inherited method, the method in the category can, as usual, invoke the inherited implementation via a message to super. However, if a category overrides a method that already existed in the category's class, there is no way to invoke the original implementation.
What this is saying to me is that if you override a method on a subclass via a category, you can call [super methodName] as you would normally, but if you override the base class method directly, you can't invoke the original.

If you dynamically provide the category override (see resolveInstanceMethod:), you can cache the previous method selector beforehand, and call that.

Related

Swift. Let to override but not to call the method

Is there any way to let the method of the superclass be overrided, but not called directly?
For example: A inherited from B. There is two methods. One is final and must be called, second is overridable but shouldn't be called, only override.
I tried #available and private but that don't fit. I think that it can be reached by delegate, but maybe there is another way?
For example, you can throw an error in your method that will say that this method shouldn't be called and child class should override it. But, of course, it is no compile time restriction, only runtime.
Also it has sense for you to read discussion here: Abstract functions in Swift Language

Why do we call doesNotRecognizeSelector: method?

I am working with socket programming.I just wanted to clear a doubt related with a code i downloaded from -mobileorchard.com - Chatty. While R&D , I saw a function call in ChatRoomViewController.m file
[chatRoom broadcastChatMessage:input.text fromUser:[AppConfig getInstance].name];
when I saw in Room.m file, for the implementation of above call; it was
- (void)broadcastChatMessage:(NSString*)message fromUser:(NSString*)name
{
// Crude way to emulate an "abstract" class
[self doesNotRecognizeSelector:_cmd];
}
i googled for "doesNotRecognizeSelector:" , according to Apple its for error handling, stating "The runtime system invokes this method whenever an object receives an aSelector message it can’t respond to or forward." my question is why does the developer call the broadcastChatMessage:fromUser: function if its none of use there and to handle which method's "selector not found" exception ?
According to Stackovrflow, its used to create abstract class , according to this Question, its to avoid "Incomplete implementation" warning.
I am still not getting why that method is used in that Chatty Code, Kindly help me to understand the reason why that method is used.
This is the method that exists on every NSObject derived object that triggers the path to an exception when a method isn't recognized in a runtime call. For example, if you try to send a message to an NSString called -foo, it'll end up there since that's not a valid method on NSString.
In this case, the Chatty class Room is a base class that is never used directly. LocalRoom and RemoteRoom derive from it, and both of those classes provide an overriding implementation of -broadcastChatMessage:fromUser. Nobody ever calls that base class version, but for "completeness" the programmer has guaranteed that a subclasser must override this by implementing the method, but then turning around and calling this to trigger an exception.
Thing is, this isn't specifically idiomatic Objective-C. An "abstract" class is a concept from C++ and other languages; it's base class that exists only as a "pattern" from which to subclass. (In ObjC, this is often done by creating a formal #protocol when there isn't meaningful state, as there (mostly) isn't here).
Note that the call to -doesNotRecognizeSelector: is arbitrary. It's not necessary to avoid compiler warnings here (since the method is in fact implemented) and the original writer could have easily just thrown an exception directly, or done nothing instead.
It seems to me that you already answered your own question. There is no method to make abstract classes in Objective-C, so the closest thing to do it to have the methods that you need to override throw exceptions. If you override this method in a subclass, then doesNotRecognizeSelector: will no longer be called. Basically it is a way to get a developer to promise to implement this method in their subclass.
Also, as you mentioned, if you don't put this in then the compiler will issue a warning because no implementation exists for a method defined in the header. This will perform the same behavior as not implementing it, but the compiler will realize that you are doing it on purpose.

Tracing back method call of overridden method in eclipse

I am looking at a source code and it has a method named updateDisplayList. There are various methods in this source code with similar name. However I am interested in one particular updateDisplayList method. I want to check where this method is getting called. I have tried using CTRL+SHIFT+G in eclipse which returns me all the references of this method in that source code. However as there are many methods with same name, those references are also getting returned. How can I know where that particular updateDisplayList method is getting called?
As stated in the comments updateDisplayList() is a Flex component life cycle method. Practically every Flex component implements this method.
If you've modified this method in one class, lets call it ClassA, and you're also seeing the effects of this modification in other classes, it must mean that the other classes inherit from ClassA in some way.
To determine who's inheriting from ClassA, you can just search for that class name in your project. This will likely find the other class that you're looking for. However, there could be a series of classes that inherit from ClassA so you might have to look deeper than that (find all the classes that extend ClassA and then search for those classes). This might be a slippery slope and may not be fruitful.
Another approach is to set a breakpoint in the updateDisplayList() method in ClassA. As I mentioned, you'll hit this breakpoint frequently. In FlashBuilder/Eclipse, you can use the "expressions" window and inspect the value of this. If this is ClassA, it's not the droid(s) you're looking for, so let execution resume.
I'm sure there are a handful of other ways to get to the bottom of this. But updateDisplayList() is such a common method, there's no point in searching for that method name :)

SenTest, Objective-C, Category Weirdness

I have a SenTest class I am attempting to write which uses a Category to override a method in a controller class. I want my mock controller class to call a method in the SenTest class to determine how to behave for various tests.
For example:
Set a var in the testFoo method.
In testFoo, call my mock controller's overridden method.
Have it call back up to the SenTest singleton to figure out how to behave for testFoo.
Is this possible, or am I an idiot?
Turns out the trick to doing this is to to make the associated reference IN the category code, not in the SenTest case.
So for example, declare this in category:
-(void)fakeMethodToSetTestData:(NSDictionary *)data;
And in that method set the associative reference to store your data "associated" with "self".
Call this in your test case on your object, passing in your data.
Then in your test case, call your:
-(void)realMethodInCategoryWhichIsBeingOverridden;
And in your category implementation of this method, retrieve the data from the associative reference you set in the first method.
This will let you set test data on a Controller so that you can hijack the delegation chain, for example, to prevent the second method from going to the network and returning your test data into your controller's code.

Help, can't call another class's method

Tried many ways based on other questions asked here but could not get a method call to another class to compile.
I'm writing a dedicated class to process arithmetic, for example class Arithmetic. It has no class variables. It subclasses no class (though I tried NSObject with failure). It will have methods of the type:
+ (NSString *)calculateEnergy:(NSString *)weight;
that I want to call from another class, in a static-method way, like:
self.label.text=[arithmetic calculateEnergy:#"8.0"];
where 'Arithmetic *arithmetic' is declared and given a retain property (synthesised etc.) in the header and implementation of the class wanting to access the calculateEnergy method.
I've tried various suggestions, such as variations on:
[(Arithmetic *) arithmetic calculateEnergy:#"8.0"];
every time getting an "Accessing unknown 'calculateEnergy' getter method"
Thank you so much in advance!
Though I don't have the complete picture, your method definition is for a class-level, static method, as opposed to an instance method. You would want to call it as
self.label.text = [Arithmetic calculateEnergy:#"8.0"];
You also would not need to create an instance of Arithmetic to call the method you have there.
Is arithmetic not an instance of Arithmetic? If instead you try self.label.text=[Arithmetic calculateEnergy:#"8.0"]; you should be OK.