2015-11-11 6 views
15

ボタンアクション(通常はセレクタ)に関数を渡すことが可能かどうか疑問に思っていました。クロージャのようなスウィフト使用セレクタ引数

例えば、通常、私が言うと思います:

UIBarButtonItem(title: "Press", style: .Done, target: self, action: "functionToCall") 

func functionToCall() { 
    // Do something 
} 

しかし、のような、それは何かをすることが可能です場合、私は思っていた:私の関数であるので、私はこれをしたい理由がある

UIBarButtonItem(title: "Press", style: .Done, target: self, action: { 
    // Do Something 
}) 

を非常にシンプルで、それはより洗練されたように思えます。彼らは閉鎖に重点を置いています。

答えて

0

残念ながらAppleが提供する初期化プログラムでは不可能です。バックグラウンドでこれが動作する方法は、リフレクションであり、クロージャを提供することは、現在サポートされていない全く異なるものです。

いくつかのハッキングを使用してカスタムソリューションを作成することは可能かもしれません。あるいはAppleが将来的にそれを導入するかもしれません。

1

のReddit上のポストは、カスタムコンポーネントと、このための解決策を説明 - https://www.reddit.com/r/swift/comments/3fjzap/creating_button_action_programatically_using

私はストーリーボードを通じてプログラム的ではなく、ボタンを追加する必要がありましたけれども、それを使用するには。ここに私がそれをした方法があった。

let tempVariableIWantToReference = "Classy" 

navigationTitle.leftBarButtonItem = BlockBarButtonItem.init(
    title: "< Back", style: UIBarButtonItemStyle.Plain, 
    actionHandler: {() -> Void in 
     print("Hey I'm in a closure") 
     print("I can even reference temporary variables. \(self.tempVariableIWantToReference)!!!") 
    }) 
10

ここスウィフト3.

class BlockBarButtonItem: UIBarButtonItem { 
    private var actionHandler: ((Void) -> Void)? 

    convenience init(title: String?, style: UIBarButtonItemStyle, actionHandler: ((Void) -> Void)?) { 
    self.init(title: title, style: style, target: nil, action: #selector(barButtonItemPressed)) 
    self.target = self 
    self.actionHandler = actionHandler 
    } 

    convenience init(image: UIImage?, style: UIBarButtonItemStyle, actionHandler: ((Void) -> Void)?) { 
    self.init(image: image, style: style, target: nil, action: #selector(barButtonItemPressed)) 
    self.target = self 
    self.actionHandler = actionHandler 
    } 

    func barButtonItemPressed(sender: UIBarButtonItem) { 
    actionHandler?() 
    } 
} 
+0

それはObjective-Cのプロパティ・ブロックのために働くのでしょうか? http://stackoverflow.com/questions/42172472/how-to-invoke-objective-c-block-property-in-swift – Aleksandr

+0

はい、objective-cと似たようなことができるはずです。 – David

+0

あなたがリンクの下の質問で見ることができるように、それは不可能であるように見えます。多分あなたはなぜ知っている?) – Aleksandr

4

の更新された解決策がありますこれは、サブクラス化せずに代替ソリューションです:

extension UIBarButtonItem { 
    private struct AssociatedObject { 
     static var key = "action_closure_key" 
    } 

    var actionClosure: (()->Void)? { 
     get { 
      return objc_getAssociatedObject(self, &AssociatedObject.key) as?()->Void 
     } 
     set { 
      objc_setAssociatedObject(self, &AssociatedObject.key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 
      target = self 
      action = #selector(didTapButton(sender:)) 
     } 
    } 

    @objc func didTapButton(sender: Any) { 
     actionClosure?() 
    } 
} 

それがObjective-Cランタイムから関連するオブジェクトに依存していますクロージャ/ブロックプロパティを追加します。

これを設定すると、ターゲットがそれ自身に変更され、セレクタが存在する場合にはクロージャを呼び出す新しい関数をポイントします。この、あなただけの任意のUIBarButtonItemactionClosureを設定し、すべてが動作することを期待することができます任意の時点で、ここでの例だと

let button = UIBarButtonItem(
    barButtonSystemItem: .action, 
    target: nil, action: nil 
) 
button.actionClosure = { 
    print("hello") 
} 
関連する問題