Objective-C Runtime: How to remove a method from a class? - objective-c-runtime

In the Objective-C Runtime Reference, I see class_addMethod but not class_removeMethod. How do I dynamically remove a method?
Also, does class_addMethod add an instance method or a class method?

As Inerdial mentioned in his comment, the main question (How can a method be removed from a class at runtime?) is somewhat exhaustively answered here.
MattDiPasquale asks as well:
Also, does class_addMethod add an instance method or a class method?
Inerdial is correct again:
class_addMethod adds an instance method, and that to add a class method, you need to add an instance method to the class' class.
Given a Class c, we can get our hands on the class of which it is an instance (known as its "metaclass") as simply as
Class metac = object_getClass(c);
To then "add a class method" to c, we add a method to metac using class_addMethod.
If, for example, elsewhere we have already defined
id myClassMethodImplementation(id self, SEL _cmd) {
//implementation
}
We can then add a class method to c as follows:
BOOL success = class_addMethod(metac, #selector(myClassMethod), (IMP)myClassMethodImplementation, "##:");
or equivalently
BOOL success = class_addMethod(object_getClass(c), #selector(myClassMethod), (IMP)myClassMethodImplementation, "##:");
To simply add this same method as an instance method on c, we simply write
BOOL success = class_addMethod(c, #selector(myClassMethod), (IMP)myClassMethodImplementation, "##:");
References:
1. Objective-C Runtime Reference 2. Objective-C Runtime Programming Guide - Type Encodings 3. Cocoa with Love - What is a meta-class in Objective-C?

Related

Objective-C passing methods as parameters

How do you pass one method as a parameter to another method? I'm doing this across classes.
Class A:
+ (void)theBigFunction:(?)func{
// run the func here
}
Class B:
- (void)littleBFunction {
NSLog(#"classB little function");
}
// somewhere else in the class
[ClassA theBigFunction:littleBFunction]
Class C:
- (void)littleCFunction {
NSLog(#"classC little function");
}
// somewhere else in the class
[ClassA theBigFunction:littleCFunction]
The type you are looking for is selector (SEL) and you get a method's selector like this:
SEL littleSelector = #selector(littleMethod);
If the method takes parameters, you just put : where they go, like this:
SEL littleSelector = #selector(littleMethodWithSomething:andSomethingElse:);
Also, methods are not really functions, they are used to send messages to specific class (when starting with +) or specific instance of it (when starting with -). Functions are C-type that doesn't really have a "target" like methods do.
Once you get a selector, you call that method on your target (be it class or instance) like this:
[target performSelector:someSelector];
A good example of this is UIControl's addTarget:action:forControlEvents: method you usually use when creating UIButton or some other control objects programmatically.
Another option is to look at blocks. It allows you to pass a block of code (a closure) around.
Here's a good write up on blocks:
http://pragmaticstudio.com/blog/2010/7/28/ios4-blocks-1
Here's the apple docs:
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/00_Introduction.html
Objective C makes this operation relatively easy. Apple provides this documentation.
To directly address your question, you are not calling a function, but a selector. Here is some sample code:
Big Function:
+ (void)theBigFunction:(SEL)func fromObject:(id) object{
[object preformSelector:func]
}
Then for class B:
- (void)littleBFunction {
NSLog(#"classB little function");
}
// somewhere else in the class
[ClassA theBigFunction:#selector(littleBFunction) fromObject:self]
Then for class C:
- (void)littleCFunction {
NSLog(#"classC little function");
}
// somewhere else in the class
[ClassA theBigFunction:#selector(littleCFunction) fromObject:self]
EDIT: Fix selectors sent (remove the semicolon)
You can use Blocks for this purpose. http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/00_Introduction.html

Creating a class whose methods can be called without an instance of an object (static class)

I'm new to objective c and i want to create a class containing certain methods that can be called in any of my other classes, mostly helper methods. im still learning the syntax and i dont know how to declare it properly
kind of like in java Integer.parseInt( );
Thanks!
Static methods in objective-c are called 'class methods' and can be declared with '+' symbol (while instance methods with '-'), e.g.:
- (void) instanceMethod;
+ (void) classMethod;
To call class method use class name:
[MyClass classMethod];
Those are called (unsurprisingly) class methods. You can declare one by using + instead of - in the method signature, e.g.
#interface MyInteger : NSObject
+ (MyInteger *)parseInt:(NSString *)str;
#end
This method is then called on the class itself, e.g. [MyInteger parseInt:#"12"].
Of course, since this is C, if your class method doesn't actually have much relation to any particular class, you could just define it as a C function instead.
NSInteger myParseInt(NSString *str);
When you see a - sign in front of a method, it's an instance method. That means you can only call that method on an instance of a class.
If you want to create a class method, all you need to do is change that - to a +.
they are called class methods. they are declared and used like this:
#interface MONClass : NSObject
+ (NSString *)convertString:(NSString *)string;
#end
in use:
NSString * converted = [MONClass convertString:string];

Calling a public method

I'm trying to figure out how to centralize a method that I use in a few of my ViewControllers. I already had a singleton that I was using for some variables. I called the singleton class Shared.
I moved my method to the Shared class and tried calling it like so:
m.createdAt = [Shared getUTCFormateDate:[messageObject objectForKey:#"created_at"]];
It's giving me an exception saying that the selector doesn't exist when it tries to call it.
I have already imported Shared.h. Any other thoughts would be appreciated.
If your class is named "Shared" then it looks like you are trying to call a class method rather than an instance method. So, you need to declare the method with + instead of -.
here is the correct pattern for creating a Singleton in objective-c: (Ill use an example of a User object.. taken from code I have open in front of me). also, please note that there is a difference between Singleton classes and Static Class methods, as discussed here.. Difference between static class and singleton pattern?
in the .h file, declare a static method that returns an instance of your class.
+(User *) currentUser;
in the .m file, create a static variable that holds your instance
static User * _user;
then, in your .m class, create your "public" static accesor GET that returns or instantiates and returns your static variable
+ (User *) currentUser
{
if (!_user)
{
_user =[[User alloc]init];
// ... init the singleton user properties and what not
// ...
}
return _user;
}
then, when you want to call on your Singleton class you just make sure that User.h is imported and call [[User currentUser] someMethodorProperty];
enjoy

objective-c static/class method definition - what is the difference between "static" and "+"?

I'm wondering if someone can explain the difference between the functions below. They are both static, but require different signature syntaxes. I'm wondering how these are handled at runtime, and why you would use one over the other?
+ (int) returnInt:(NSString *)myString1 withString2:(NSString *)myString2
{
if ([myString1 isEqualToString:myString2])
return 1;
else
return 0;
}
vs.
static int returnInt(NSString *myString1, NSString *myString2)
{
if ([myString1 isEqualToString:myString2])
return 1;
else
return 0;
}
Thanks!
Unlike in (say) C++, where static member functions are just ordinary functions in the class' namespace, Objective-C has proper class methods.
Since classes are objects, calling a class method is really like calling an instance method on the class. The main consequences of this are:
1) Calling a class method incurs a slight (although generally inconsequential) overhead, since method calls are resolved at runtime.
2) Class methods have an implicit 'self' argument, just like instance methods. In their case, 'self' is a pointer to the class object.
3) Class methods are inherited by subclasses.
together, 2 and 3 mean that you can do stuff like this with a class method:
+ (id) instance
{
return [[[self alloc] init] autorelease];
}
then create a new class that inherits the method and returns a new instance of itself, rather than the superclass.
I believe that marking an ordinary c function static will just make it unavailable to files other than the one it's defined in. You'd generally do this if you wanted to make a helper function that is only relevant to one class and you wanted to avoid polluting the global namespace.

In Objective-C, when should I use class methods and when should I use instance methods?

What is the difference between class and instance methods in Objective-C and when should I use each of them?
Using the tired old Car analogy...
Think of a Class like it is a factory that makes Instances of the class. For example, you might have a Car class and you might declare a method like:
+ carWithColor: (NSColor *) aColor;
And that method would then create a new Car instance, set the color, and return it:
+ carWithColor: (NSColor *) aColor
{
Car *aCar = [[[self alloc] init] autorelease];
[aCar paintWithColor: aColor];
return aCar;
}
Now, that Car class would then declare an instance method that allows the car to be painted. Why an instance method? Because every car can have a different color (and the color of the car would likely be stored in an instance variable).
- (void) paintWithColor: (NSColor *) aColor
{
... do your paint stuff here ...
}
This is explained in the Objects, Classes, and Messaging section of the Objective-C documentation.
This is an old post, but since it comes up first in a Google search I thought I'd add to it.
I'm not going to talk about class methods used as factory methods. I'd like to talk about their use in utility methods. You can/should use class methods for utility methods that are independent of state. What does this mean? Well, for instance, if you're formatting a date the same way for all instances, that's a utility method that should be a class method. Think of the utility method like a screw driver. You don't need to make a new instance of the screw driver every time you want to do something with it. The screw driver remains constant. So, for instance, I have a class that includes a private method that generates a string of emDashes used for displaying to the view. This method is not dependent on state and hence will not vary by instance. Think of class utility methods like constants.
+ (NSString *)emDashString {
return #" \u2014 \u2014 \u2014 \u2014 \u2014 \u2014 \u2014 \u2014 \u2014";
}
You can call this method generically within the class (it's private in my example) like this:
NSString *string = [[self class] emDashString ];
I've deliberately chosen a bit of a trivial example to drive the point home. You would only bother making this a class utility method if you're going to need this string more than once in your class. Notice that instead of referring to the class by name I call it generically with [self class] since this is called internally. If it's exposed and you want to call it from another class then refer to it by the class name as usual.
Instance methods do things with instances of a class:
NSString *myString;
myString = [[[NSString alloc] initWithString:#"Hello, world."] autorelease];
NSLog (#"myString's length: %u", [myString length]); // instance method
Class methods can do class-specific things without relying on an object instance, often returning an instance of the class, or some other class-specific result:
NSLog (#"%#", [NSString stringWithString:#"Hello, world."]); // class method
I think it may be rare to see class methods that do not return something.
You don't need to implement both. Either option is available to you as you design your class.
An instance method can operate on an instance of the class. This can get or set a property, or cause behavior you only want that instance to perform. You need to actually have an instance to use it. These can either use or change the state of the instance.
// Notional instance methods
myHouse.color = blueColor;
[myCar accelerate];
speed = myCar.speed;
A class method operates on the notion that the class exists. It can be used to create an instance, or perform a calculation that doesn't depend on having an instance. You might have a class for custom math helper, that essentially contains functions.
// Notional class method uses
myString = [NSString stringWithFormat:#"&f", floatToConvert];
myResult = [MyMathHelper MyFunctionWithInput:myInput];
Class method signatures are prefixed with +, instance methods with - so in your header file declarations would look something like this:
-(void)setAllThings:(NSArray*)things; //instance method
+(void)setAllClassThings:(NSArray*)things; //class method
And of course the same rules apply when you define the methods in the .m file.