18

I want to set the delegate of an object inside a class method in Objective-C. Pseudo-code:

+ (ClassWithDelegate*) myStaticMethod {
    if (myObject == nil) {
        myObject = [[ClassWithDelegate alloc] init];
        // myObject.delegate = ?
    }
    return myObject;
}

In Java I would simply create an anonymous class that implemented the delegate protocol. How can I do something similar in Objective-C?

Basically I would like to avoid creating a separate class (and files) to implement a simple delegate protocol.

Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
hpique
  • 119,096
  • 131
  • 338
  • 476
  • possible duplicate of [Anonymous delegate implementation in Objective-C?](http://stackoverflow.com/questions/766475/anonymous-delegate-implementation-in-objective-c) – Dave DeLong Sep 22 '10 at 15:11
  • @Dave DeLong Clarified title to differentiate from that question. In this case the context is a static method. – hpique Sep 22 '10 at 15:27
  • the context doesn't matter. You have to provide an object (`id`) as a delegate, and the other question quite clearly answers that there is no such thing as an anonymous class in Objective-C (yet), so you're going to have to use a normal object. – Dave DeLong Sep 22 '10 at 15:31
  • There are no static methods in Objective-C. There are instance messages and class messages. – JeremyP Sep 22 '10 at 15:32
  • 1
    @Dave DeLong Most likely my question is poorly phrased, but I don't see them as the same question. Yes, there are no anonymous classes in Obj-C. But my question is: what's the best way to do in Obj-C class messages what anonymous classes allow me to do in Java static methods? – hpique Sep 22 '10 at 19:18

3 Answers3

20

As JeremyP has rightly said, There are no anonymous classes in Objective C like there are in Java.

But in Java, anonymous classes are mostly used to implement single method interface or what we also call as a functional interface.

We do it to avoid having to implement the interface** in a class **just for one method implementation which is most commonly used for Listeners, Observers and event handlers.

This is mostly done because of **lack of anonymous first class functions in Java (prior to version 8 and project lambda).

Objective C has something called as blocks, where you can directly pass a block which contains the implementation of that single method rather than an empty class wrapping it up.

Example:

A use of Anonymous Class in Java

//Functional interface
interface SomethingHandler 
{
  void handle(Object argument);
}

//a method that accepts the handler in some other class
class SomeOtherClass
{ 
  void doSomethingWithCompletionHandler(SomethingHandler h){
      // do the work that may consume some time in a separate thread may be.
      // when work is done call the handler with the result which could be any object
      h.handler(result);
  };
}

// Somewhere else in some other class, in some other code
// passing the handler after instantiating someObj as an object of SomeOtherClass which can use the handler as needed
SomeOtherClass someObj = new SomeOtherClass();
someObj.doSomethingWithCompletionHandler( new SomethingHandler()
                        {
                              void handle(Object argument)
                              {
                                // handle the event using the argument
                              }
                         });

In Objective C

// declare the handler block 
typedef void (^SomethingHandler)(id argument){}

// this interface is different than Java interface  which are similar to Protocols
@interface SomeOtherClass
 -(void)doSomethingWithCompletionHandler:(SomethingHandler)h;
@end

@implementation SomeOtherClass
 -(void)doSomethingWithCompletionHandler:(SomethingHandler)h
 {
          // do the work that may consume some time in a separate thread may be.
          // when work is done call the handler with the result which could be any object
          h(result);
 }

@end

  // passing the handler after instantiating someObj as an object of SomeOtherClass which can use the handler as needed

SomeOtherClass* someObj = [[SomeOtherClass alloc] init]; // ARC :)

[someObj doSomethingWithCompletionHandler:^(id argument)
                                            {
                                               // handle the event using the argument
                                            }];
Amogh Talpallikar
  • 12,084
  • 13
  • 79
  • 135
16

There are currently no anonymous classes in Objective-C.

Often you can use an already existing object. For instance, for an NSTableViewDataSource, you can implement the methods in the document or view controller and pass that as the delegate.

Or you can have the object itself implement the protocol and make it its own delegate in the default case.

Or the methods that send the delegate messages can check for a nil delegate and do something sensible in that situation.

Or you can declare and define a class inside the implementation file you are creating the object that needs a delegate.

JeremyP
  • 84,577
  • 15
  • 123
  • 161
  • Thanks JeremyP! So basically in this case I could define an ad-hoc class in the implementation file, create an instance in the class message and assign it as delegate. Would that be correct? – hpique Sep 22 '10 at 16:03
2

Anonymous classes can be implemented with library. Several months ago I have worked on MMMutableMethods fork to improve old implementation (discussing with author) and to add my own mechanism without any obj-c runtime manipulation.

https://github.com/k06a/MMMutableMethods

A. First mechanism works on obj-c runtime class creation:

MM_CREATE(MM_REUSE,^(Class class){
    [class addMethod:@selector(onResultWithId:)
        fromProtocol:@protocol(AMCommandCallback)
            blockImp:^(id this,id res){
                NSLog(@"onResultWithId: %@",res);
            }];
    [class addMethod:@selector(onErrorWithJavaLangException:)
        fromProtocol:@protocol(AMCommandCallback)
            blockImp:^(id this,JavaLangException *e){
                NSLog(@"onErrorWithJavaLangException: %@",e);
            }];
})

B. Second mechanism works on simple message forward implementation:

MM_ANON(^(MMAnonymousClass *anon){
    [anon addMethod:@selector(onResultWithId:)
       fromProtocol:@protocol(AMCommandCallback)
           blockImp:^(id this,id res){
               NSLog(@"onResultWithId: %@",res);
           }];
    [anon addMethod:@selector(onErrorWithJavaLangException:)
       fromProtocol:@protocol(AMCommandCallback)
           blockImp:^(id this,JavaLangException *e){
               NSLog(@"onErrorWithJavaLangException: %@",e);
           }];
})

First one creates new obc-j classes in runtime, it allows you to create classes MM_CREATE_CLASS(MM_REUSE, *) and directly instances with MM_CREATE(MM_REUSE, *). Classes will be created only on first execution and reused by default, but you can avoid reusing by calling MM_CREATE_CLASS_ALWAYS(*) and MM_CREATE_ALWAYS(*).

The second mechanism doesn't creates any runtime instances, just remember blocks for selectors and forward method calls to them.

I prefere second way not to create a lot of classes in runtime. IMHO it is much safer and enough powerful.

To use this library just:

pod 'MMMutableMethods', :git => 'https://github.com/k06a/MMMutableMethods'
k06a
  • 17,755
  • 10
  • 70
  • 110