Swift 4 Completion Handler
Create a simple function …
func f(input: String, completion: (_ result: String) -> String ) -> String {
let a = completion("Inside completion \(input)")
return "Here is a: \(a)"
}
Now call it as follows …
let r = f(input: "command input ...") {
(result: String) in
return ("got back: \(result)")
}
You’ll get the following result:
Here is a: got back: Inside completion command input ...
Closures - Escaping
Closures must be escaping when work is done asynchronously or stored.
func getSumOf(array:[Int], handler: @escaping ((Int)->Void)) {
var sum: Int = 0
for value in array {
sum += value
}
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2), execute: {
handler(sum)
})
}
Now calling this function …
func doSomething() {
getSumOf(array: [16,756,442,6,23]) { (sum) in
print(sum)
}
}
doSomething()
// Output 1243
Here’s a way you could test the above function.
func testGetSumOf() {
let expectation = self.expectation(description: "Sum up values")
getSumOf(array: [16,756,442,6,23]) { (sum) in
print(sum)
XCTAssert(sum == 1243, "Sum should equal 1243")
expectation.fulfill()
}
waitForExpectations(timeout: 5, handler: nil)
}
Extending this example
func getSumMulOf(array:[Int],
handler: @escaping (([Int])->Int)) {
var sum: Int = 0
var mul: Int = 1
for value in array {
sum += value
mul *= value
}
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2), execute: {
print("sum+mul: \(handler([sum,mul]))")
})
}
And now testing this…
func testGetSumMulOf() {
let expectation = self.expectation(description: "Sum up values")
getSumMulOf(array: [16,756,442,6,23]) { (result) in
print(result)
XCTAssert(result[0] == 1243, "Sum should equal 1243")
XCTAssert(result[1] == 737807616, "Sum should equal 737807616")
expectation.fulfill()
return result[0]+result[1]
}
waitForExpectations(timeout: 3, handler: nil)
}