web-dev-qa-db-ja.com

iOS Swiftクロージャをプロパティとして渡しますか?

カスタムUIViewがあるとしましょう。MyCustomViewという名前にします。このビュー内には、UITextFieldプロパティがあります。私の目標は、MyCustomViewのインスタンスを作成し、それをどこかのビューコントローラに追加できるようにすることであり、そのビューコントローラがそのテキストフィールドで行われたアクションを処理できるようにしたいとします。たとえば、テキストフィールド内のキーボードで「return」キーを押した場合、何らかのアクションを実行したい場合があります。目的のcの疑似コードで想定していることの例を挙げましょう。

MyCustomView *myView = [[MyCustomView alloc] initWithFrame:CGRectMake(10,10,100,100)];
myView.textField.actionBlock = { /* do stuff here! */ }
[self.view addSubview:myView];

そして、MyCustomViewクラスの中で次のようにします。

- (BOOL)textFieldShouldReturn:(UITextField *)textField  {
    self.actionBlock();
    return NO;
}

CustomViewをUITextFieldDelegateにしたいので、これを行うたびに、追加先のビューコントローラーにすべてのデリゲートメソッドを追加する必要はなく、ただ1つの実装を行うだけです- whatever私はそれに渡します...これを迅速に行うにはどうすればよいですか?

17
Mike

もちろん、これを行うことができます。 Swiftにはファーストクラスの関数があるため、関数を変数のように直接渡すなどのことを実行できます。関数自体は実際には舞台裏のクロージャです。基本的な例を次に示します:

class MyClass {
    var theClosure: (() -> ())?

    init() {
        self.theClosure = aMethod
    }

    func aMethod() -> () {
        println("I'm here!!!")
    }
}


let instance = MyClass()
if let theClosure = instance.theClosure {
    theClosure()
}

instance.theClosure = {
    println("Woo!")
}
instance.theClosure!()

そして、これは文字列パラメータを取ることができるクロージャを使用する同じ例です。

class MyClass {
    var theClosure: ((someString: String) -> ())?

    init() {
        self.theClosure = aMethod
    }

    func aMethod(aString: String) -> () {
        println(aString)
    }
}

let instance = MyClass()
if let theClosure = instance.theClosure {
    theClosure(someString: "I'm the first cool string")
}

instance.theClosure = {(theVerySameString: String) -> () in
    println(theVerySameString)
    someThingReturningBool()
}
instance.theClosure!(someString: "I'm a cool string!")
41
Mick MacCallum