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)
  }