2017-06-05 6 views
0

UIAlertControllerの設定を1行に単純化するために使用する関数に、配列内のアラートアクションを渡そうとしています。 ボタンのタイトルを正常に渡すことはできますが、アラートアクションは成功させることはできません。 ここに私がやっていることがあります。パラメータとして配列内のクロージャ/ブロックを渡す

+(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です。 私は迅速なファイルをいくつか書いていますが、私は上記の方法を以下のように迅速に呼び出しています。

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) 

私がクロージャを渡してもうまくいかない場合、OKをクリックするとクロージャを渡すとクラッシュします。 私はまた、コレクションとして渡されたときにブロックをコピーする必要があることを発見しました。しかし、私はこれを行いましたが、まだ分かりません。私はここで何をする必要があるか教えてくれますか?

おかげ

答えて

-1

よりもむしろ変換おかしなを扱う、なぜ単にネイティブ迅速なバージョンを作ってみませんか?あなたはiPhone上で簡単な警告をしたい場合は、単にviewController.presentAlert(title: "Error", message: "Something broke")を行うことができますので、それはまた、iPadの差と、いくつかの素敵なデフォルトを扱う

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) 
    } 
} 

は、ここで同じ機能の私のバージョンです。

1

問題は、SwiftクロージャがObjective-Cブロックとは異なる種類のオブジェクトであるため、ブロックとして実行しようとするとクラッシュするという問題です。

通常、スウィフトコンパイラはブロックタイプパラメータを使用して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 –

関連する問題