2016-07-12 3 views
2

初期化子引数としてオプションの閉鎖を取ります引数を引数としてクロージャを渡して実行するにはどうすればよいですか?クラス<code>A</code>の

class A { 
    var closure:()? 

    init(closure: closure()?) { 
     self.closure = closure 
     self.closure() 
    } 
} 

私は閉鎖などの引数を持つ関数を渡したい:

class B { 
    let a = A(closure: action(1)) // This throws the error: Cannot convert value of type '()' to expected argument type '(() -> Void)?' 

    func action(_ i: Int) { 
     //... 
    } 
} 

クラスAは、引数でクロージャactionを実行する必要がありi

これを正しく記述する方法についてはわかりませんが、上記のコードコメントのエラーを参照してください。何を変えなければならないのですか?

+0

の最初には、それは関数型ではない、それは無効ですオプション。とにかく、あまり意味をなさない。あなたが探している言葉は、部分的に適用される関数です。 –

+2

@ValentinRadu "あなたが探している言葉は、部分的に適用された関数です"いいえ、それはありません。 – matt

+0

@mattケアを説明してください?すべての引数が部分的に適用された部分的に適用された関数があります。 Swiftを含む多くの言語でこれが可能です。 'func(a:Int)(){}'これに感覚があるかどうかは、別の質問です。 –

答えて

4

あなたをしてください"あなたは何を持っているの"コードエラーフリーです。上記のように与えられたA

class A { 
    typealias ClosureType =()->Void 

    var closure: ClosureType? 

    init(closure: ClosureType?) { 
     self.closure = closure 
     //`closure` would be used later. 
    } 

    //To use the closure in class A 
    func someMethod() { 
     //call the closure 
     self.closure?() 
    } 
} 

、あなたのクラスBを書き換える必要があります:

このようなあなたのクラスAを想定し

class B { 
    private(set) var a: A! 
    init() { 
     //initialize all instance properties till here 
     a = A(closure: {[weak self] in self?.action(1)}) 
    } 

    func action(i: Int) { 
     //... 
    } 
} 
+0

クラスAでクロージャを実行するにはどうしたらいいですか? 'self.closure'と' self.closure?() 'のどちらもうまくいかないようです。 – Manuel

+0

'self.closure?()'が動作するはずです。あなたはそのコードをどこに置いたのですか? – OOPer

+0

私の悪い、 'self.closure = closure'を設定するのを忘れました。ここのコード例では書いたが、元のコードでは忘れてしまった: - | – Manuel

5

closure()?タイプではありません。 ()?はタイプですが、おそらくあなたが望むタイプではありません。

var closureにその値として特定の種類の機能を持たせたい場合は、宣言でその関数の型を使用する必要があります。

var closure: (Int) -> Void 

あなたはinit(closure:)は、そのパラメータとしての機能の特定の種類を取りたい場合は同様に、あなたは、例えば、宣言でその関数の型を使用する必要があります

私はあなたがしようとしていると思う何をする1つの方法は次のコードである
init(closure: (Int) -> Void) { 
+0

実際には、引数は 'Int'ではなくカスタムの' enum'です。クラスAとクラスBで列挙型を宣言したくない場合、回避策はありますか? – Manuel

+0

enumには名前が必要です。そのため、Intを使用する場所でその名前を使用してください。型は型です。 – matt

+2

マット:ハイジャックへの私の謝罪(オフトピック)、しかし私はビートです:あなたは時間があれば、私のコメントにコメント/説明がありますか[この質問](http:// stackoverflow .com/questions/38336982/en -ations-of-en-enumations#comment64091487_38336982)、私が同値であると考えていたことについて'case' ...' switch'文のパターンマッチングと 'if case ... 'を使ったパターンマッチング(別の質問を投稿することができましたが、私がコメントした質問には非常に近いでしょう) 。 – dfri

1

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     let _ = A.init(){Void in self.action(2)} 
    } 

    func action(i: Int) { 
     print(i) 
    } 
} 


class A: NSObject { 
    var closure :()? 

    init(closure: (()->Void)? = nil) { 
     // Notice how this is executed before the closure 
     print("1") 
     // Make sure closure isn't nil 
     self.closure = closure?() 
    } 
} 
1

タイプスウィフトで

をパラメータとして、すべてのオブジェクトは型があります。たとえば、Int,Stringなどは、あなたがよく知っているすべてのタイプです。

したがって、関数を宣言するときは、パラメータの明示的な型(または時にはプロトコル)を指定する必要があります。

func swallowInt(number: Int) {} 

化合物の種類

はスウィフトはまた、化合物の種類の概念があります。その一例がタプルです。タプルは他の型のコレクションに過ぎません。

let httpStatusCode: (Int, String) = (404, "Not Found") 

機能を容易に引数としてタプルを取ることができる:

func swallowStatusCode(statusCode: (Int, String)) {} 

別の化合物の種類は、関数型です。関数型は、パラメータのタプルと戻り値の型で構成されます。したがって、上記のswallowInt関数の関数型は、(Int) -> Voidです。同様に、IntStringを取り、Boolを返す関数の型は、(Int, String) -> Boolです。パラメータ

として

関数型だから我々は再書き込み機能Aにこれらの概念を使用することができます。

class A { 
    var closure: (() -> Void)? 

    init(closure: (() -> Void)?) { 
     self.closure = closure 
     self.closure() 
    } 
} 

引数を渡すと、そしてちょうど次のようになります。

func foo(closure: (Int) -> Void) { 
    // Execute the closure 
    closure(1) 
} 

関連する問題