Syntax for adding a closure to a function? - swift

I'm trying to create a function that has a closure. Nothing is passed to the function, just after it finishes another function has to be called. Something like this:
func addGradient(closure: syntax) {
(closure: _ in ("function call here") )}
so it can be called similiar to this
addGradient(closure: "function to be called")

Just use the signature for the function minus any of the names:
func doIt(one: Int, two: String) -> [String] {
…
}
Would have the closure signature of:
(Int, String) -> [String]
So yours would be:
func addGradient(closure: (Int, String) -> [String]) {
…
}
And you can call it like this:
addGradient(closure: doIt)
One more note, a function like this:
func doAgain() {
…
}
Has a closure signature of this:
() -> ()

Related

Pass a closure in a function

I have a little experience in Swift and facing a problem to pass a closure in a function as a parameter.
//1.
public func changeMyStatus(to f:?, _ completion:#escaping (_ isSucced:Bool)->()){
//
}
//2.
func goLive(_ completion:#escaping (_ isSucced:Bool)->()){
}
//3.
func goNonLive(_ completion:#escaping (_ isSucced:Bool)->()){
}
Now , I want to use first function in my controller and wants to pass second/third function as a parameter. Closure in first will return true/false depending on what returned by closure in second/third.
i)What will be the type I should put in first function?
Also I want to call first function from my class like this
changeMyStatus(to: goNonLive) { (isSuccess) in
}
please help
You need to change the changeMyStatus function signature and implementation like:
public func changeMyStatus(to f: (#escaping (Bool) -> ()) -> () , _ completion:#escaping (_ isSucced:Bool)->()){
f { (status) in
completion(status)
}
}
You can call these function like:
// goLive
changeMyStatus(to: goLive(_:)) { (status) in
print(status)
}
// goNonLive
changeMyStatus(to: goNonLive(_:)) { (status) in
print(status)
}
Your second and third function has a completion parameter with a type of : (Bool -> Void) -> Void
So in order to pass it to your first function, try this way :
public func changeMyStatus(to f: ((Bool) -> ()), _ completion:#escaping (_ isSucced:Bool)->()) { // Your body}
In Swift, you need to see a function as a type like Int, Double, String...

Closure trailing variable

I have this closure as variable:
public var cellClicked: (name: String, number: Int)?
How can I make it a trailing closure, so I can do something like:
cell.cellClicked!{
(str: String, n: Int) in
}
What you have declared is tuple not the closure, If you want to make closure declared it like this.
public var cellClicked: ((String,Int) -> ())?
And make call like this
cell.cellClicked = { (name, value) in
}
SWIFT 3.0
Try this.
public var cellClicked = (String, Int) -> Void
cell.cellClicked = {(str,n) in
}
You can use as below :
func myMethod(completionHandler: #escaping (_ param : type, _ param2 : type) -> Void)
Description of #escaping -> https://cocoacasts.com/what-do-escaping-and-noescaping-mean-in-swift-3/

Function with optional completion block in Swift [duplicate]

This question already has answers here:
Can swift closures be set to a default value when used as a parameter in a function?
(4 answers)
Closed 6 years ago.
When I create a function, I can make a parameter optional by giving it a default value, like this:
func foo(bar: String = "foobar") {}
I want to do the same (make it optional) with a completion block. I have tried the following:
func foo(completionBlock: (foo: String) -> () = () -> ())
func foo(completionBlock: (foo: String) -> () = (foo: String) -> ())
func foo(completionBlock: (foo: String) -> () = ((foo: String) -> ()))
func foo(completionBlock: (foo: String) -> () = ((foo: String) in))
func foo(completionBlock: (foo: String) -> () = {(foo: String) in})
How can I do this?
EDIT: This is/was a duplicate question, sorry for that. However, I couldn't find the solution in the original question. So nathan's answer is the best one
If you want to default to nil:
func foo(completionBlock: ((String) -> ())? = nil) {
}
If your default completion block is very simple, you can put it right in the function's definition:
// A default completion block that is simple enough to fit on one line
func foo(completionBlock: (String) -> () = { result in print(result) }) {
// ...
}
// A default completion block that does nothing
func foo(completionBlock: (String) -> () = {} ) {
// ...
}
If your default completion block is more complex, you can define it as a separate function:
func defaultCompletion(result: String) {
// ...
}
func foo(completionBlock: ((String) -> ()) = defaultCompletion) {
}
In Swift 3:
func foo(completionBlock: (String) -> () = { _ in }) {}

How to pass closure with argument as argument and execute it?

Initializer of class A takes an optional closure as argument:
class A {
var closure: ()?
init(closure: closure()?) {
self.closure = closure
self.closure()
}
}
I want to pass a function with an argument as the 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) {
//...
}
}
Class A should execute the closure action with argument i.
I am not sure about how to write this correctly, see error in code comment above. What has to be changed?
Please make your "what-you-have-now" code error free.
Assuming your class A like this:
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?()
}
}
With A given above, you need to rewrite your class B as:
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) {
//...
}
}
The problem is that closure()? is not a type. And ()? is a type, but it is probably not the type you want.
If you want var closure to have as its value a certain kind of function, you need to use the type of that function in the declaration, e.g.
var closure: (Int) -> Void
Similarly, if you want init(closure:) to take as its parameter a certain kind of function, you need to use the type of that function in the declaration, e.g.
init(closure: (Int) -> Void) {
Types as Parameters
In Swift, every object has a type. For example, Int, String, etc. are likely all types you are extremely familiar with.
So when you declare a function, the explicit type (or sometimes protocols) of any parameters should be specified.
func swallowInt(number: Int) {}
Compound Types
Swift also has a concept of compound types. One example of this is Tuples. A Tuple is just a collection of other types.
let httpStatusCode: (Int, String) = (404, "Not Found")
A function could easily take a tuple as its argument:
func swallowStatusCode(statusCode: (Int, String)) {}
Another compound type is the function type. A function type consists of a tuple of parameters and a return type. So the swallowInt function from above would have the following function type: (Int) -> Void. Similarly, a function taking in an Int and a String and returning a Bool would have the following type: (Int, String) -> Bool.
Function Types As Parameters
So we can use these concepts to re-write function A:
class A {
var closure: (() -> Void)?
init(closure: (() -> Void)?) {
self.closure = closure
self.closure()
}
}
Passing an argument would then just be:
func foo(closure: (Int) -> Void) {
// Execute the closure
closure(1)
}
One way to do what I think you're attempting is with the following code:
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?()
}
}

No trailing closures support for methods with default parameter values?

You can drop the code below into playgrounds.
import UIKit
class MyClass {
func foo(a: String, b: () -> ()) {
b()
}
func bar(a: String = "a", b: () -> ()) {
b()
}
}
let object = MyClass()
object.foo("x") { () -> () in
println("foo")
}
object.bar() { () -> () in
println("foo")
}
object.bar() call produces Missing argument for parameter 'b' in call
The question is: am I doing something wrong, or trailing closures are not supported in methods with default parameter values?
It does look like a problem with trailing closures - this code works:
object.bar(b: { () -> () in
println("foo")
})
However if the external name is removed:
func bar(a: String = "a", _ b: () -> ()) {
b()
}
this no longer works:
object.bar({ () -> () in
println("foo")
})
Moreover using a function having a string as the 2nd parameter:
func test( val1: String = "a", val2: String) {
}
the default parameter is correctly assigned, so this succeeds:
test("me")
which is a different behavior than using closures.
Conclusion: a method or function with parameter(s) having default value and a trailing closure does not work if at least one of the parameters with default value is not specified. Avoiding the trailing closure the function works only if the parameter has external name.