Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS Swift Pass Closure as Property?

Tags:

Let's say I have a custom UIView, lets call it MyCustomView. Inside this view is a UITextField property. Suppose my goal is to be able to create an instance of MyCustomView and add it to some view controller somewhere, and I want that view controller to be able to handle actions taken on that text field. For example, if I hit "return" on the keyboard within the text field, I may want to do some action - let me give an example of what I'm envisioning with some objective-c psuedo code:

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

And then inside the MyCustomView class I would do something like:

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

I'd like the customView to be the UITextFieldDelegate so that every time I do this I won't have to add all the delegate methods to the view controllers I'm adding it to, but rather have a single implementation that just does whatever I pass to it... How would one go about doing this in swift?

like image 940
Mike Avatar asked Jun 13 '14 02:06

Mike


People also ask

What is closure property in Swift?

In Swift, a closure is a special type of function without the function name. For example, { print("Hello World") } Here, we have created a closure that prints Hello World .

Can a closure be passed parameters?

Because closures can be used just like strings and integers, you can pass them into functions. The syntax for this can hurt your brain at first, so we're going to take it slow. If we wanted to pass that closure into a function so it can be run inside that function, we would specify the parameter type as () -> Void .

How do you return a value from a closure in Swift?

Instead, in the closure, take the return value that you want in the cell and store it somewhere (in a member variable) and have the tableView update it itself (e.g. with tableView. reloadData() ). This will cause it to get the cell again (cellForRow ...).


1 Answers

Sure, you can do this. Swift has first class functions, so you are able to do things like directly pass functions around like variables. Keep in mind, functions themselves are in fact closures behind the scenes. Here's a basic example:

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!() 

And here is the same example using closures that can take a String parameter.

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!") 
like image 84
Mick MacCallum Avatar answered Sep 18 '22 13:09

Mick MacCallum