7

In my application i have an UIViewController that i uses a lot of UIAlertView to ask things to the user.

Because i need the response of each UIAlertView i have made my controller a delegate of UIAlertViewDelegate, this works fine but after 7 UIAlertView's i`m trying to find a better way to use delegates.

In java i know that i can create inline classes for a single purpose, like in this question: Java - inline class definition

What i want to know is: Is there a way to create a class to be delegate dynamically? to achieve something like this

id<UIAlertViewDelegate> myCustomClass = @class {
    my class code goes here
}

UIAlertView* alertView;
alertView = [[UIAlertView alloc] initWithTitle:@"Title"
                                       message:@"Message"
                                      delegate:myCustomClass
                             cancelButtonTitle:@"No"
                             otherButtonTitles:@"OK", @"Sure", @"Maybe", nil] ];    
[alertView show];
2
  • @class has a totally different meaning in Obj-C than what you are thinking. It declares a 'forwarding class' of sorts, FYI. Commented Oct 1, 2012 at 14:19
  • 1
    the point of using @class is just to show something similar, to help me explain to anyone what i am thinking. just that Commented Oct 1, 2012 at 17:11

2 Answers 2

14

No - there are no 'inline classes' in Objective-C. With that said, you can create custom objects at run-time with objective-c, which is a little bit more involved, but I'd be willing to share some code to do what you are saying.

Here is an example of that:

NSObject+Subclass.h

#import <objc/runtime.h>

typedef struct selBlockPair { SEL aSEL; id (^__unsafe_unretained aBlock)(id, ...); } selBlockPair;
#define NIL_PAIR ((struct selBlockPair) { 0, 0 })
#define PAIR_LIST (struct selBlockPair [])
#define BLOCK_CAST (id (^)(id, ...))

@interface NSObject (subclass)

+(Class) newSubclassNamed:(NSString *) name
            protocols:(Protocol **) protos
                 impls:(selBlockPair *) impls;

@end

NSObject+Subclass.m

@implementation NSObject (subclass)

+(Class) newSubclassNamed:(NSString *)name
             protocols:(Protocol **)protos
                 impls:(selBlockPair *)impls
{
    if (name == nil)
    {
        // basically create a random name
        name = [NSString stringWithFormat:@"%s_%i_%i", class_getName(self), arc4random(), arc4random()];
    }

    // allocated a new class as a subclass of self (so I could use this on a NSArray if I wanted)
    Class newClass = objc_allocateClassPair(self, [name UTF8String], 0);

    // add all of the protocols untill we hit null
    while (protos && *protos != NULL)
    {
        class_addProtocol(newClass, *protos);
        protos++;
    }

    // add all the impls till we hit null
    while (impls && impls->aSEL)
    {
        class_addMethod(newClass, impls->aSEL, imp_implementationWithBlock(impls->aBlock), "@@:*");
        impls++;
    }

    // register our class pair
    objc_registerClassPair(newClass);

    return newClass;
}

@end

Example Usage:

int main()
{
    @autoreleasepool {
        __strong Class newClass = [NSString newSubclassNamed:@"MyCustomString" protocols:NULL impls: PAIR_LIST {
            @selector(description),
            BLOCK_CAST ^id (id self) {
                return @"testing";
            },
            NIL_PAIR
        }];

        NSString *someString = [newClass new];
        NSLog(@"%@", someString);
    }
}

Output:

2012-10-01 10:07:33.609 TestProj[54428:303] testing
Sign up to request clarification or add additional context in comments.

5 Comments

Your response answered all my questions about inline classes and opened another bunch of questions about your code. Thank you for real. now I'm trying to understand this code that you posted. thanks again
@NicosKaralis no problem, if you have any issues understanding, don't be afraid to ask!
Brilliant! One quick question, is there an easy way to call [super description] in the custom impl?
@ccwasden You can use objc_msgSendSuper, just read the documentation for that and you should be all set!
@RichardJ.RossIII Thank you for your such a nice explanation .
3

This type of Java anonymous inner class is not something that is supported in Objective-C. If you want to respond to the delegates individually, I good way is to experiment with blocks.

Unfortunately, Apple has not added blocks into UIAlertViews, but you can implement them yourself. A bunch of people have done this online. Take a look here: http://blog.mugunthkumar.com/coding/ios-code-block-based-uialertview-and-uiactionsheet/ or https://github.com/MugunthKumar/UIKitCategoryAdditions .

The basic idea is that you can create a subclass (or a category if using associated objects), that will be its own delegate and tell its own delegate to call a block you pass in

1 Comment

Your answer help me a lot too, tanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.