views:

331

answers:

5

This is an objective-c question.

I would like to call a method in an object, but there is no instantiation of the object. Is this possible?

The method I want to call is not a class method.

+4  A: 

Unless the method is static you will not be able to do this. static routines in Objective-C will be prepended with a +. For example NSObject provides these two routines (among many):

+ (id)alloc; // static - an NSObject instance is not required
- (NSString*)description; // nonstatic - an NSObject instance is required

One would make the respective calls like so:

NSObject* result = [NSObject alloc];
NSString* desc = [result description];
fbrereto
+5  A: 

You can't call a method on an object that doesn't exist. But you can call a method on a class even if you have no instantiated objects of that class. (That's what alloc is in @fbrereton's answer -- a class method).

Class methods are declared and defined with a + instead of a -, are called on the class rather than the instance, and cannot access self or any instance variables in the class (for reasons that should be obvious).

cdespinosa
Would you clal this a "static method" in this language?
Joe Philllips
@d03boy in Objective-C we call these "class" methods, but they are functionally equivalent to static methods used in other languages
Dave DeLong
They're more than static methods, because object-c class's are real objects just like instances. For example the -[NSArray array] method is dynamic in that it returns an instance of the receiver. [NSMutableArray array] results in a mutable array, but NSMutableArray doesn't have to override that method. It's able to do that by implementing the method like this: "return [[[self alloc] init] autorelease]". That works because 'self' is NSMutableArray in one case, and NSArray in the other. So, in objective-c, you can have polymorphic class methods.
Jon Hess
A: 

You can indeed invoke an instance method without an instance, provided it is functionally a class method (that is, it accesses no instance variables). Here's an example:

/*
Compile with:
gcc -framework Foundation inst_method_without_inst.m -o inst_method_without_inst
*/
#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@interface Foo : NSObject {
}
- (BOOL)doSomethingWithThis:(NSString *)this;
@end

@implementation Foo
- (BOOL)doSomethingWithThis:(NSString *)this {
  NSLog(@"Look, it's this: %@", this);
  return YES;
}
@end

typedef BOOL (*my_sel_t)(id, SEL, NSString *);
int
main(void) {
  Class cls = [Foo class];
  SEL my_sel = @selector(doSomethingWithThis:);
  Method m = class_getInstanceMethod(cls, my_sel);
  // You could also use +[NSObject instanceMethodForSelector:] to get |m|,
  // since |cls| is a kind of NSObject.
  my_sel_t f = (my_sel_t)method_getImplementation(m);
  BOOL result = f(nil, my_sel, @"Hello from an instanceless instance method invocation!");
  NSLog(@"result: %d", (int)result);
  return EXIT_SUCCESS;
}

You could get it to work even if the instance method accesses instance variables by allocating memory for it to work with (using either +alloc or class_getInstanceSize() plus malloc()) and passing a pointer to that memory as the first id argument to the implementation instead of nil.

While this is entertaining as an exercise, I can't think of a good reason to not just instantiate the class and use the standard messaging syntax and compiler support. In fact, the only reason we couldn't just do [(Foo *)nil doSomethingWithThis:@"BOO!"] here is that objc_msgSend() special-cases messages to nil with the result that NO is returned and nothing happens.

Jeremy W. Sherman
+1  A: 

Perhaps you just want a plain-old C function. If you don't want a class method, and you don't want an instance method, that appears to be your only option. Don't be afraid of using C functions in Objective-C. Every technique has its place.

Jonathan Sterling
+2  A: 

Sorry to nit-pick Chris' terminology, but we don't call a method on an object in Objective-C, we send a message to an object. When you send a message, the runtime will look up the appropriate method and call it. The distinction matters.

NSResponder