Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly use a UIAlertAction handler in Objective-C

Simply put, I would like to call a method or reference a variable from my class in a UIAlertAction handler.

Do I need to pass in a block to this handler or is there some other means to achieve this?

@interface OSAlertAllView ()
@property (nonatomic, strong) NSString *aString;
@end

@implementation OSAlertAllView

+ (void)alertWithTitle:(NSString *)title message:(NSString *)msg cancelTitle:(NSString *)cancel inView:(UIViewController *)view
{
    __weak __typeof(self) weakSelf = self;

    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:msg
                                                                preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:cancel style:UIAlertActionStyleDefault
        handler:^(UIAlertAction * action) {
            // I'd like to reference a variable or method here
            weakSelf.aString = @"Apples"; // Not sure if this would be necessary
            self.aString = @"Apples"; // Member reference type 'struct objc_class *' is a pointer Error
            [self someMethod]; // No known class method Error
        }];

    [alert addAction:defaultAction];
    [view presentViewController:alert animated:YES completion:nil];
}

- (void)someMethod {

}
like image 528
Antonioni Avatar asked Nov 20 '15 17:11

Antonioni


1 Answers

The + at the start of your alertWithTitle... method means it is a class method. When you call it, self will be the class OSAlertAllView, not an instance of type OSAlertAllView.


There are two ways you could change it to make it work.

Change the + at the start of the method to a - making it an instance method. Then you would call it on an instance instead of the class.

// Old Class Method Way
[OSAlertAllView alertWithTitle:@"Title" message:@"Message" cancelTitle:@"Cancel" inView:viewController];

// New Instance Methods Way
OSAlertAllView *alert = [OSAlertAllView new];
[alert alertWithTitle:@"Title" message:@"Message" cancelTitle:@"Cancel" inView:viewController];

The other way would be to create an instance to OSAlertAllView inside of you alertWithTitle... and replace the uses of self with that object.

+ (void)alertWithTitle:(NSString *)title message:(NSString *)msg cancelTitle:(NSString *)cancel inView:(UIViewController *)view
{
    OSAlertAllView *alertAllView = [OSAlertAllView new];

    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:msg
                                                                preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:cancel style:UIAlertActionStyleDefault
        handler:^(UIAlertAction * action) {
            alertAllView.aString = @"Apples";
            [alertAllView someMethod];
        }];

    [alert addAction:defaultAction];
    [view presentViewController:alert animated:YES completion:nil];
}
like image 109
Craig Siemens Avatar answered Nov 08 '22 22:11

Craig Siemens