Say that I have 2 functions:
functionA(#escaping closureA: ((Double) -> ())) {
// Some Code for function A
}
functionB(#escaping closureB: ((Double) -> ())) {
// Some Code for function B
}
If I want to call functionB from function A, how do I pass function A's closure parameter as argument to functionB's parameter?
Something that looks like this:
func A(#escaping closureA: ((Double) -> ())) {
// Some Code for function A
B(<trying to pass closureA>)
}
func B(#escaping closureB: ((Double) -> ())) {
// Some Code for function B
}
You need to escape the in parameter to the closure to start with and then when calling the closure sent to functionB you need to supply a value as argument
func functionA(closureA: (#escaping (Double) -> ())) {
functionB(closureB: closureA)
}
func functionB( closureB: (#escaping (Double) -> ())) {
closureB(3.2)
}
Example
functionA(closureA: {print($0 * 2.0)})
6.4
Try this example below.
func functionA(closure:(()->Void), completionHandler: #escaping (Double) -> Void) {
closure()
completionHandler(1.0)
}
func functionB(completionHandler: #escaping (Double) -> Void) {
completionHandler(2.0)
}
func nestedClosure() {
functionA(closure: {
functionB { (value) in
print("\(value)")
}
}, completionHandler: { (value) in
print("\(value)")
})
}
Related
I am a Javascripter and I love using the not/negate function:
function not (predicateFunc) {
return function () {
return !predicateFunc.apply(this, arguments);
};
}
I am trying to do the same thing with swift:
func not <A> (_ f: #escaping (_ A: Any) -> Bool) -> (A) -> Bool {
return { a in !f(a) }
}
But I am getting errors like
generic parameter 'T' could not be inferred
and
Cannot convert value of type '(_) -> Bool' to expected argument type '(Any) -> Bool'
The outcome I am looking for is when I have a function like this:
func isEmpty<T: Collection>(collection: T) -> Bool {
return collection.count == 0
}
I can just create a notEmpty function like this:
let notEmpty = not(isEmpty)
And then use it like
notEmpty([3,4,5]) // true
What am I doing wrong?
Using Any is a code smell. You can just extend Collection directly:
extension Collection {
var notEmpty: Bool {
return !isEmpty
}
}
[1, 3, 5].notEmpty // true
Your functional definition of not can work like this:
func not <A> (_ f: #escaping (_ a: A) -> Bool) -> (A) -> Bool {
return { a in !f(a) }
}
But to call it you would need something like this:
let arrayNotEmpty = not { (array: [Int]) in array.isEmpty }
arrayNotEmpty([1, 3, 5]) // true
You have two errors:
You're using A as both the type parameter and as the argument name.
You're using Any as the argument type instead of using the type parameter (A) as the argument type.
Try this:
func not<A>(predicate: #escaping (A) -> Bool) -> (A) -> Bool {
return { !predicate($0) }
}
Note that in this version, I'm not using argument names for the predicate argument. You don't need an argument name in the declaration ((A) -> Bool) and I'm using the anonymous argument name ($0) in the body.
Okay, so you want to write this:
func isEmpty<T: Collection>(collection: T) -> Bool {
return collection.count == 0
}
func not<A>(_ predicate: #escaping (A) -> Bool) -> (A) -> Bool {
return { !predicate($0) }
}
let notEmpty = not(isEmpty)
And you get this error:
let notEmpty = not(isEmpty)
^ Generic parameter 'A' could not be inferred
The problem is that this code tries to create a generic closure, but Swift doesn't support generic closures.
That is to say, what would the type of nonEmpty be? It would be something like:
<A: Collection>(A) -> Bool
and Swift doesn't support that.
Assuming I have 2 functions foo and bar defined below.
func foo(completion: #escaping (Response) -> Void)
func bar(a: Int, completion: #escaping (Response) -> Void)
Then I have 2 different functions that use foo and bar
func doSomethingWithFoo() {
foo { response in
handleResponse(response)
}
}
func doSomethingWithBar() {
bar(a: 42) { response in
handleResponse(response)
}
}
doSomethingWithFoo and doSomethingWithBar are very similar. They do the exact same thing with response they get in the completion callback.
My question is: is there a way in Swift to generalize doSomethingWithFoo and doSomethingWithBar? Maybe something in line with the following.
func doSomething(<???>) {
<???> { response in
handleResponse(response)
}
}
<???> is a placeholder for passing either foo or bar or even any other function that also accepts a callback of type (Response) -> Void.
I'll appreciate any help/insights. Thanks.
You can declare a function like this :
func doSomething(fooBar: (_ completion: #escaping (String) -> Void) -> Void) -> Void {
fooBar(handleResponse)
}
Which you would call like this:
doSomething(fooBar: { bar(a: 42, completion: $0) })
doSomething(fooBar: foo)
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...
Here is a function:
func foo(completion: (jsonData: String) -> ()) {
}
In Swift 3, you can't have argument labels. Therefore, this is the code:
func foo(completion: (String) -> ()) {
}
The issue with this, is that when I call the function it looks like this:
foo(completion: { _ in
})
So, if I want to see the value of jsonData, I can't because it's an underscore. How would I solve this issue?
It's working:
func foo(completion: (String) -> ()) {
completion("Hi")
}
foo { jsonData in
print(jsonData) // Output: Hi
}
For example:
func f(x: Int) -> Int {
return x
}
func h(f: #escaping (Int) -> Any) {
if (f is (Int) -> Int) {
print(f(1))
} else {
print("invalid")
}
}
h(f: f)
I expect it to print out 1 but it actually prints out invalid.
There's a workaround using generics:
func intF(x: Int) -> Int {
return x
}
func stringF(x: Int) -> String {
return "\(x)"
}
func h<T>(f: (Int) -> T) {
if (T.self == Int.self) {
print(f(1))
} else {
print("invalid")
}
}
h(f: intF) // prints: 1
h(f: stringF) // prints: invalid
Using Any is almost always a sign of code smell, you should try to rely as much as possible of the type safety that Swift provides. You can achieve this by making h generic, thus verifiable at compile time.
// the overload that does the actual stuff
func h(f: #escaping (Int) -> Int) {
print(f(1))
}
// this maps to all other types
func h<T>(f: #escaping (Int) -> T) {
print("invalid")
}
h { _ in return "15" } // Invalid
h { 2 * $0 } // 2
Heck, you could even give up the generic overload, thus you'll have for free compile checks instead of runtime failures (much, much reliable and predictive)
You can rewrite h into a generic function:
func h<T>(f: #escaping (Int) -> T) {
if T.self == Int.self {
print(f(1))
} else {
print("invalid")
}
}
But the better way to to write type-specific overloads for h and a generic catch-all for the rest (if you need it at all).