将数组中的闭包/块作为参数iOS传递

时间:2017-06-05 15:46:13

标签: ios objective-c swift closures

我正在尝试将数组中的警报操作传递给用于将UIAlertController配置简化为一行的函数。 能够成功传递按钮标题但不能通过警报操作。 这就是我在做的事情。

+(void)showAlertWithTitle:(NSString*)title 
                  message:(NSString*)alertmessage 
             buttonTitles:(NSArray*)buttonTitles 
            buttonActions:(NSArray*)buttonActions 
         inViewController:(UIViewController*)viewController {

    UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:alertmessage preferredStyle:UIAlertControllerStyleAlert];

    [buttonTitles enumerateObjectsUsingBlock:^(NSString* buttonTitle,NSUInteger idx,BOOL *stop){
         UIAlertAction *action = [UIAlertAction actionWithTitle:buttonTitle style:UIAlertActionStyleDefault handler: [[buttonActions objectAtIndex:idx] copy]]; //blocks should always be copied to heap from stack else they will crash
        [alert addAction:action];
    }];

    [viewController presentViewController:alert animated:YES completion:nil];

}

上面的代码文件是长期写的,所以它的目标是c。 我已经写了一些快速的新文件,我在swift中调用上面的方法,如下所示。

 CommonManager.showAlert(withTitle: "", message: "Feedback Sent", 
       buttonTitles: ["Ok"], buttonActions: [ { (action: UIAlertAction) in

                    print("you pressed Ok alert button");

                    // call method whatever u need
                }], in: self)

如果我没有通过关闭它工作正常,如果通过关闭点击确定它崩溃。 我还发现我们需要复制一个块,当它作为一个集合传递时,我做了那个但是有些东西仍然不对,我无法弄明白。你能告诉我在这里需要做什么吗?

由于

2 个答案:

答案 0 :(得分:1)

问题是Swift闭包是一种与Objective-C块不同的对象,所以试图以块的形式运行它会崩溃。

通常,如果Swift编译器发现您正在使用块类型参数将闭包传递给Objective-C方法,它会将Swift闭包转换为Objective-C块,但在这种情况下,它只是看到你是把它放在一个数组中,而不是该方法在数组中对它做什么,所以它不进行任何转换。

我能弄明白让它发挥作用的唯一方法就是:

 CommonManager.showAlert(withTitle: "", message: "Feedback Sent", 
       buttonTitles: ["Ok"], buttonActions: [ { (action: UIAlertAction) in

                    print("you pressed Ok alert button");

                    // call method whatever u need
                } as (@convention(block) (UIAlertAction) -> Void)!], in: self)

答案 1 :(得分:-1)

为什么不制作原生的swift版本,而不是处理转换怪异?

这是我的相同功能版本:

extension UIViewController {

    func presentAlert(title: String, message: String, actions: [UIAlertAction] = [UIAlertAction(title: "OK", style: .cancel, handler: nil)], iPadOrigin: CGRect? = nil, style: UIAlertControllerStyle = .alert, animated: Bool = true, completion: (() -> ())? = nil) {

        let alert = UIAlertController(title: title, message: message, preferredStyle: style)
        actions.forEach(alert.addAction)
        alert.popoverPresentationController?.sourceView = self.view
        if let iPadOrigin = iPadOrigin {
            alert.popoverPresentationController?.sourceRect = iPadOrigin
        }

        present(alert, animated: animated, completion: completion)
    }

    func presentAlert(title: String, message: String, actions: [UIAlertAction] = [UIAlertAction(title: "OK", style: .cancel, handler: nil)], iPadButtonOrigin: UIBarButtonItem? = nil, style: UIAlertControllerStyle = .alert, animated: Bool = true, completion: (() -> ())? = nil) {

        let alert = UIAlertController(title: title, message: message, preferredStyle: style)
        actions.forEach(alert.addAction)
        alert.view.tintColor = Color.BlueDarker
        alert.popoverPresentationController?.barButtonItem = iPadButtonOrigin

        present(alert, animated: animated, completion: completion)
    }
}

它还可以处理iPad差异和一些不错的默认设置,因此如果你想在iPhone上进行简单的提醒,你可以viewController.presentAlert(title: "Error", message: "Something broke")