0

I'm using a UIAlertView + block Category found here.

I'm having trouble following how he has created the blocks:

typedef void (^DismissBlock)(int buttonIndex);

I understand this, use it on creating my own blocks. So I created mine:

typedef void (^DismissBlockWithView)(UIAlertView *alertview, int buttonIndex);

I think I understand what is happening with the setter method:

- (void)setDismissBlock:(DismissBlock)dismissBlock
{
    objc_setAssociatedObject(self, &DISMISS_IDENTIFER, dismissBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

From what I understand, this is a lower level way to set a variable. I'm not sure where, when, or why it should be used. Please correct me if I'm mistaken. It is setting the referenced value of DIMISS_IDENTIFER to the dismissBlock object.

So for my block:

-(void)setDismissBlockWithView:(DismissBlockWithView)dismissBlockWithView {
    objc_setAssociatedObject(self, &ALERT_VIEW, dismissBlockWithView, OBJC_ASSOCIATION_COPY_NONATOMIC);
    objc_setAssociatedObject(self, &DISMISS_IDENTIFER, dismissBlockWithView, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

I set each variable.

Now the part I'm having trouble understanding is the getter method:

- (DismissBlock)dismissBlock
{
    return objc_getAssociatedObject(self, &DISMISS_IDENTIFER);
}

So the objc_getAssociatedObject() takes in id object and const void *key variables. Can you only have a single variable when creating blocks in this manner? I know I don't know the underlying logic behind all this, just kinda trying to use common sense logic to put it all together.

What do I need to do to change it so I can have the UIAlertView and the buttonIndex returned?

I want the UIAlertView returned because I am taking in user input (using the UIAlertViewStylePlainTextInput style option) through it and the text is stored in the alert view.

2
  • 1
    Try reading this first nshipster.com/associated-objects Commented Apr 29, 2015 at 19:42
  • 1
    Why can't you use @property (copy) DismissBlockWithView dismissBlock;? Commented Apr 29, 2015 at 19:46

2 Answers 2

2

The objective-c associative references methods are part of the runtime API which allows you to "attach" objects to other objects at runtime. In your case you're associating blocks with the alert-view, allowing you to access these blocks when necessary (when the alert is dismissed for example).

The DIMISS_IDENTIFER in your code is simply the association key, which you can later use to retrieve the associated object - the block. Think of it as a key to a dictionary which stores the associated object and used to identify it.

You can associate a single object per key. In the method setDismissBlockWithView you associated the same block with the alert-view but with different keys, I don't think there's much use for that. The new block signature which you've created is just fine, you can pass the alert-view when executing the block. As an example, I modified one of the methods from UIAlertView+MKBlockAdditions to call the dismissBlock with your signature, passing both the alert-view and the index to the block:

+ (void)alertView:(UIAlertView*) alertView didDismissWithButtonIndex:(NSInteger) buttonIndex {
        if(buttonIndex != [alertView cancelButtonIndex]){
            if (alertView.dismissBlock) {
                alertView.dismissBlock(alertView, buttonIndex - 1);
            }
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

1

You can think of Associated Objects as a lower-level way to set a property on an object. It's not that, exactly, but it's close enough for purposes of discussion. Check out this NSHipster piece for information on Associated Objects.

I'm not sure where, when, or why it should be used.

The answer is, almost never. Seriously. If you ever find yourself typing "objc_", you should stop right there, and ask yourself what you're trying to do, because there's probably a better way. The Objective-C Runtime is wonderful and powerful and terrible, and it's not to be trifled with. See again the NSHipster link above.

One use case for Associated Objects is to add instance variables or properties to a class via a class category or extension, something that's otherwise not possible, and that's exactly what UIAlertView+MKBlockAdditions.m is using them for. It's not how I'd have done it; I'd have subclassed UIAlertView, and added regular @propertys to achieve that functionality. In fact, I did that, a couple years ago. :)

But, I think we might be off in the weeds here. With all this talk of blocks and associated objects, aren't you really just trying to get some text out of a UIAlertView that has a text field in it?

If so, you'll be using alertViewWithTitle:message:cancelButtonTitle:otherButtonTitles:onDismiss:onCancel: to create the alert. You pass your block as the onDismiss: parameter, and you can get the text field using textFieldAtIndex:. It should look something like this:

__block UIAlertView* alert = [UIAlertView alertViewWithTitle:@"Hi!"
                            message:@"What's your name?"
                cancelButtonTitle:@"Cancel"
                otherButtonTitles:@[@"OK"]
                        onDismiss:^(int buttonIndex)
                        {
                            UITextField* nameField = [alert textFieldAtIndex:0];
                            NSLog( @"Hello, %@", nameField.text );
                        }
                          onCancel:nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;

[alert show];

1 Comment

So simple and to the point. I like it, thank you very much. And thank you for the info on objc__ commands. I edited it to add __block so the variable can be used in the block.

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.