Reputation: 4100
How do I make so that a Swift function returns a value and has a completion handler at the same time? The idea is that the function first returns a provisional result, and then the final result. Something like:
func method(completion: (Int) -> ()) {
return 2
... some processing ...
completion(3)
}
let a:Int = method(completion: { (new) -> Void in
a = new
})
Upvotes: 0
Views: 1172
Reputation: 11243
You got it upside down. You have to use the completion handler for the intermediate results and the return for the final result. Once you call the return, the control comes out of the function.
func method(completion: (Int) -> ()) -> Int {
completion(1)
//
//
completion(2)
//
//
return 3
}
And handle the result like this.
let a: Int = method(completion: { (new) -> Void in
print(new)
})
print(a)
OR
Have two completion handlers instead.
func foo(provisionalCompletion: (Int) -> (), finalCompletion: (Int) -> ()) {
provisionalCompletion(someValue)
//
//
provisionalCompletion(someValue)
//
//
finalCompletion(finalValue)
}
You can invoke it and handle the intermediate results and final results like this.
foo(completion: { (provisionalValue) in
// Handle provisional value
}) { (finalValue) in
// Handle final value
}
The second approach is more flexible, but also confusing sometimes. You have to be careful to call the final completion only when you have reached the final result. Or you could add a return after every final. But then again you have to make sure your final result is reached.
Upvotes: 1
Reputation: 318774
You are close. You need to kick off some background process (the whole point of a completion handler) and then do the return
.
func method(completion: @escaping (Int) -> ()) -> Int {
DispatchQueue.global().async {
var x = 0
for y in 0...10_000 {
x += y
}
completion(3)
}
return 2
}
var aRes = 0
aRes = method(completion: { (new) -> Void in
aRes = new
print("2", aRes)
})
print("1", aRes)
This will result in:
1 2
2 3
with the second line appearing after a delay.
Note that you can't do:
var aRes = method(completion: { (new) -> Void in
aRes = new
print("2", aRes)
})
This results in an error "Variable used within its own initial value".
Upvotes: 1