2017-06-05 26 views
0

我试图将数组中的警报操作传递给用于将UIAlertController配置简化为一行的函数。 我能够成功传递按钮标题,但不是警报操作。 这是我正在做的事情。将数组中的闭包/块作为参数传递iOS

+(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中,我正在用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) 

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

感谢

回答

-1

而不是处理转换的怪事,为什么不只是做一个原生迅速的版本?

这里是我的版本相同的功能:

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的分歧和一些不错的默认值,所以你可能只是做viewController.presentAlert(title: "Error", message: "Something broke"),如果你想在iPhone上一个简单的警报。

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) 
+0

该解决方案为我工作,谢谢@newacct –