26

Is it possible to declare anonymous implementations of things like Delegates in Objective-C. I think I have the terminology right, but here's a java example:

myClass.addListener(new FancyInterfaceListener({
    void onListenerInterestingAction(Action a){
        ....interesting stuff here
    }
});

So for example to handle an UIActionSheet call I have to declare another method in the same class, which seems a bit silly if I want to pass it data, because I'd have to store that data as a global variable. Here's an example of deleting something with a confirmation dialog asking you if your sure:

-(void)deleteItem:(int)indexToDelete{
    UIActionSheet *confirm = [[UIActionSheet alloc] initWithTitle:@"Delete Item?" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Delete" otherButtonTitles:nil];
    [confirm showInView:self.view];
    [confirm release];
}

and the UIActionSheetDelegate in the same class:

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
    if (buttonIndex == 0){
        [[Settings sharedSettings] removeItemAtIndex:/*need index variable here*/];
        [drinksTable reloadData];
    }
}

What I want to be able to do is declare it inline, just like I did in the java example at the top. Is this possible?

rustyshelf
  • 44,963
  • 37
  • 98
  • 104
  • I just write a posible solution for this kind of situations [here](https://github.com/GojaN/AnonymusDelegate). Keep in mind that this is a proof of concept. – Bruno Berisso Nov 05 '12 at 14:21
  • Yep, you can do it with 3rd-party libraries, read my full answer here: http://stackoverflow.com/a/33096839/440168 – k06a Oct 13 '15 at 07:42

5 Answers5

17

There is no way to do this in Objective-C currently. Apple has published some work on their efforts to add blocks (really more like lambda closures than anonymous classes) to the language. You would likely be able to do something similar to the anonymous delegate with those.

In the mean time, most Cocoa programmers add the delegate methods to a separate category on the delegate class. This helps to keep the code more organized. In the .m file for the class in your example, I would do something like this:

@interface MyClass (UIActionSheetDelegate)
- (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex;
@end

@implementation MyClass
//... normal stuff here
@end

@implementation MyClass (UIActionSheetDelegate)
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
    if (buttonIndex == 0){
        [[Settings sharedSettings] removeItemAtIndex:/*need index variable here*/];
        [drinksTable reloadData];
    }
}
@end

Xcode's method popup in the editor window will separate the category's declaration and implementation from the main class'.

Barry Wark
  • 107,306
  • 24
  • 181
  • 206
  • Do you need to have the interface declaration for each protocol you implement? If so, that's a lot more work. (I've never declared the methods in an implemented protocol in my interface, on the premise that simply declaring the protocol "implemented" was good enough.) – Greg Maletic Apr 08 '10 at 18:45
  • 1
    No, you can declare multiple protocols, just use a comma in the interface. Also, most code I've seen, rather than using a category like this (this isn't really what the feature is designed for -- it's designed to allow you to extend classes you don't have the implementation to without subclassing), simply separates the code into its own section in the file with `#pragma mark` directive. – Colin Barrett May 16 '10 at 02:05
4

Objective-C doesn't have a notion of anonymous classes like Java's, so you can't create a class "inline" like in the Java code.

mipadi
  • 398,885
  • 90
  • 523
  • 479
  • Fair enough, so is there any way to do this more elegantly than creating another method in the same class? What if I wanted two different UIActionSheets? – rustyshelf Apr 20 '09 at 02:16
  • For two action sheets you would use the tag property to see which one called the delegate method. If you get into many situations like this tho, I think the responsibility of that controller might be too great. There is nothing more elegant than the way you have it. You have to keep track of the item index yourself as far as I know. – Jab Apr 20 '09 at 14:28
2

I was looking for something different when I came across this but if you do a search for UIALERTVIEW+BLOCKS you will find several hits for doing inline UIALERTVIEWs. This is the one I've been using: ALERTVIEW w/blocks

KevinOlive
  • 31
  • 2
1

I believe that anonymous classes can be implemented in Objective-C, but it will take a lot of NSProxy magic and IMP madness. This is one of my current projects.

Jonathan Sterling
  • 18,320
  • 12
  • 67
  • 79
0

How about a class implementing the delegate interface. On initialization it would take a block. In the delegate definition it calls this block.

This allows multiple UIActionSheets to exist simultaneously without having to compare on identity.

arithma
  • 438
  • 5
  • 13