如何执行 UIAlertAction 的处理程序?

Posted

技术标签:

【中文标题】如何执行 UIAlertAction 的处理程序?【英文标题】:How can I perform the handler of a UIAlertAction? 【发布时间】:2015-04-21 13:42:58 【问题描述】:

我正在尝试编写一个帮助程序类以允许我们的应用同时支持UIAlertActionUIAlertView。但是,在为UIAlertViewDelegate 编写alertView:clickedButtonAtIndex: 方法时,我遇到了这个问题:我看不到在UIAlertAction 的处理程序块中执行代码的方法。

我试图通过在一个名为 handlers 的属性中保留一组 UIAlertActions 来做到这一点

@property (nonatomic, strong) NSArray *handlers;

然后像这样实现一个委托:

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

    UIAlertAction *action = self.handlers[buttonIndex];
    if (action.enabled)
        action.handler(action);

但是,没有 action.handler 属性,或者确实没有任何我能看到的方法来获取它,因为 UIAlertAction 标头只有:

NS_CLASS_AVAILABLE_ios(8_0) @interface UIAlertAction : NSObject <NSCopying>

+ (instancetype)actionWithTitle:(NSString *)title style:(UIAlertActionStyle)style handler:(void (^)(UIAlertAction *action))handler;

@property (nonatomic, readonly) NSString *title;
@property (nonatomic, readonly) UIAlertActionStyle style;
@property (nonatomic, getter=isEnabled) BOOL enabled;

@end

还有其他方法可以执行UIAlertActionhandler 块中的代码吗?

【问题讨论】:

这可能不是您正在寻找的答案(我不确定这是否可能),但是您是否尝试过为您的操作传递一些块而不是使用处理程序?因此,根据所选索引保留要运行的操作的另一个数据源。 @timgcarlson 我是否还需要提供一种方法来传递操作的文本、样式和启用性? 【参考方案1】:

经过一些实验,我才明白这一点。原来handler块可以强制转换为函数指针,函数指针可以被执行。

像这样

//Get the UIAlertAction
UIAlertAction *action = self.handlers[buttonIndex];

//Cast the handler block into a form that we can execute
void (^someBlock)(id obj) = [action valueForKey:@"handler"];

//Execute the block
someBlock(action);

【讨论】:

这是使用非公共 API 吗?如果是,Apple 不会让该应用上架。 我不知道苹果会不会为它开发一个应用程序。我将它用于单元测试(不是作为 App 二进制文件的一部分构建的)。 如果您尝试在句柄内外执行相同的代码块,我会将代码重构为单独的方法,或者将代码移动到块中并执行处理程序。在单元测试之外,我想不出为什么需要执行 UIAlertAction 处理程序。 我正在尝试制作一个包装类,以便我可以同时使用 UIAlertController 和 UIAlertView 来保持 iOS 7 的兼容性。【参考方案2】:

包装类很棒,嗯?

.h

@interface UIAlertActionWrapper : NSObject

@property (nonatomic, strong) void (^handler)(UIAlertAction *);
@property (nonatomic, strong) NSString *title;
@property (nonatomic, assign) UIAlertActionStyle style;
@property (nonatomic, assign) BOOL enabled;

- (id) initWithTitle: (NSString *)title style: (UIAlertActionStyle)style handler: (void (^)(UIAlertAction *))handler;

- (UIAlertAction *) toAlertAction;

@end

.m:

- (UIAlertAction *) toAlertAction

    UIAlertAction *action = [UIAlertAction actionWithTitle:self.title style:self.style handler:self.handler];
    action.enabled = self.enabled;
    return action;

...

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

    UIAlertActionWrapper *action = self.helpers[buttonIndex];
    if (action.enabled)
        action.handler(action.toAlertAction);

您所要做的就是确保将UIAlertActionWrappers 插入helpers 而不是UIAlertActions。

这样,您可以让所有属性都可以根据自己的喜好获取和设置,并且仍然保留原始类提供的功能。

【讨论】:

请用随附的评论解释任何反对意见,以便我知道将来如何更好地回答:)

以上是关于如何执行 UIAlertAction 的处理程序?的主要内容,如果未能解决你的问题,请参考以下文章

UIAlertAction 处理程序延迟后运行

在 UIAlertAction 处理程序中更新 UI

未调用 UIAlertAction 处理程序

UIAlertAction 的处理程序有点太晚了——我怎样才能让它立即生效?

UIAlertAction - 处理动作

你应该如何处理 UIAlertAction 的闭包参数