Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you pass a variable to the UIAlertView delegate?

How do you pass a variable to the UIAlertView delegate?

I have a variable that I want to use in the alert view delegate. It is only used in the function that shows the UIAlertView and the UIAlertView delegate, so i don't think it should be a property on the controller. Is there a way to attach the variable to UIAlertView and retrieve it in the delegate?

- (void) someUserCondition:(SOCode *)userCode {
    if ([userCode warrentsConfirmation] > 0) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Title" message:@"Are you sure?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK",nil];        
        [alert setAlertViewStyle:UIAlertViewStyleDefault];  
        //TODO somehow store the code variable on the alert view
        [alert show];
    }
}

- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex   {
    NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
    if ([title isEqualToString:@"OK"]){
       SOCode *userCode = //TODO somehow get the code from the alert view
       [self continueWithCode:code];
    }                                 
}
like image 729
wusher Avatar asked Apr 30 '12 17:04

wusher


3 Answers

in .h before interface:

extern const char MyConstantKey;
@interface ViewController...

in .m import:

import <objc/runtime.h>

in .m before implementation

const char MyConstantKey;

in .m implementation

-(void)viewDidAppear:(BOOL)animated{ //or wherever

    NSString *aString = @"This is a string";

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Testing" message:@"test is test" delegate:self cancelButtonTitle:@"Okay" otherButtonTitles:nil];

    [alert show];

    [alert release];

    objc_setAssociatedObject(alert, &MyConstantKey, aString, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

 }

in .m alertview callback

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{

     NSString *associatedString = objc_getAssociatedObject(alertView, &MyConstantKey);

     NSLog(@"associated string: %@", associatedString);

}
like image 195
warpedspeed Avatar answered Nov 20 '22 17:11

warpedspeed


Use Associated Objects. It is described in more detail here: Your New Friends: Obj-C Associated Objects

To set the object you use use:

objc_setAssociatedObject(alert, &key, userCode, OBJC_ASSOCIATION_RETAIN);

And then to get it back:

SOCode *userCode = objc_getAssociatedObject(alertView, &key);

You also need to add static char key; so that it is in the scope of moth methods.

Update

I have wrapped this into a category on UIAlertView. You can use Cocoapods to bring it in:

pod 'HCViews/UIAlertViewHCContext', '~> 1.2'

The source is available here: https://github.com/hypercrypt/HCViews/blob/master/Categories/UIAlertView%2BHCContext.h

like image 43
hypercrypt Avatar answered Nov 20 '22 19:11

hypercrypt


A lot of posts talk about the concepts behind associated objects (which is good!) but sometimes you just want to see the code. Here's a clean and quick category that you can either put in a separate file or above the interface of one of your existing .m files (you could even replace UIAlertView with NSObject and effectively add a context property to any object):

#import <objc/runtime.h>

@interface UIAlertView (Private)
@property (nonatomic, strong) id context;
@end

@implementation UIAlertView (Private)
@dynamic context;
-(void)setContext:(id)context {
    objc_setAssociatedObject(self, @selector(context), context, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(id)context {
    return objc_getAssociatedObject(self, @selector(context));
}
@end

And then you'll be able to do something like:

NSObject *myObject = [NSObject new];

UIAlertView *alertView = ...
alertView.context = myObject;

IMPORTANT: And don't forget to nil the context in dealloc!!

like image 7
lobianco Avatar answered Nov 20 '22 18:11

lobianco