将变量添加到块

Adding a variable to a block

我正在使用 UIAlertView + 块类别 found here

我无法理解他是如何创建块的:

typedef void (^DismissBlock)(int buttonIndex);

我明白这一点,用它来创建我自己的块。所以我创建了我的:

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

我想我明白 setter 方法发生了什么:

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

据我了解,这是设置变量的较低级别的方法。我不确定应该在何处、何时或为何使用它。如果我弄错了,请纠正我。它正在将 DIMISS_IDENTIFER 的引用值设置为 dismissBlock 对象。

所以对于我的街区:

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

我设置了每个变量。

现在我难以理解的部分是 getter 方法:

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

所以 objc_getAssociatedObject() 接受 id objectconst void *key 变量。以这种方式创建块时,您只能有一个变量吗?我知道我不知道这一切背后的基本逻辑,只是有点想用常识逻辑把它们放在一起。

我需要做些什么来更改它以便我可以返回 UIAlertView 和 buttonIndex?

我想要返回 UIAlertView,因为我正在通过它接收用户输入(使用 UIAlertViewStylePlainTextInput 样式选项)并且文本存储在警报视图中。

objective-c 关联引用方法是运行时 API 的一部分,它允许您在运行时 "attach" 对象到其他对象。在您的情况下,您将块与警报视图相关联,允许您在必要时访问这些块(例如,当警报被解除时)。

代码中的 DIMISS_IDENTIFER 只是关联键,稍后您可以使用它来检索关联的对象 - 块。将其视为存储关联对象并用于标识它的字典的键。

您可以为每个键关联一个对象。在方法 setDismissBlockWithView 中,您将同一块与警报视图相关联但使用不同的键,我认为这没有多大用处。您创建的新区块签名就可以了,您可以在执行区块时通过警报视图。例如,我修改了 UIAlertView+MKBlockAdditions 中的一种方法,以使用您的签名调用 dismissBlock,同时将警报视图和索引传递给块:

+ (void)alertView:(UIAlertView*) alertView didDismissWithButtonIndex:(NSInteger) buttonIndex {
        if(buttonIndex != [alertView cancelButtonIndex]){
            if (alertView.dismissBlock) {
                alertView.dismissBlock(alertView, buttonIndex - 1);
            }
        }
    }

您可以将关联对象视为在对象上设置 属性 的低级方法。确切地说,不是这样,但它已经足够接近讨论的目的了。查看 this NSHipster piece 以获取有关关联对象的信息。

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

答案是,几乎从来没有。严重地。如果您发现自己在输入 "objc_",您应该就此停下来,问问自己您要做什么,因为可能有更好的方法。 Objective-C Runtime 很棒,很强大,但也很糟糕,不容小觑。再看上面的NSHipsterlink

关联对象的一个​​用例是通过 class 类别或扩展将实例变量或属性添加到 class,这在几年前是 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。 :)

但是,我认为我们可能会在这里杂草丛生。关于块和关联对象的所有这些讨论,您真的只是想从具有文本字段的 UIAlertView 中获取一些文本吗?

如果是这样,您将使用 alertViewWithTitle:message:cancelButtonTitle:otherButtonTitles:onDismiss:onCancel: 创建警报。您将块作为 onDismiss: 参数传递,您可以使用 textFieldAtIndex: 获取文本字段。它应该看起来像这样:

__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];