2

Can someone explain what completionHandler: ((Bool) -> Void) means?

For instance it appears when requesting camera access:

AVCaptureDevice.requestAccess(for: AVMediaType.depthData, completionHandler: (<#T##(Bool) -> Void#>))

I usually do this to check if access was granted or not:

func requestCamera() {
        AVCaptureDevice.requestAccess(for: AVMediaType.video) { (response) in
            if response {
                print("true")
            } else {
                print("denied")
            }
        }

    }

Obviously I do stuff there, but that doesn't matter here. I just want to understand what ((Bool) -> Void) means and why I have to use the completion handler here. With other functions I can just set the handler to nil, but in this case it expects a response in some way.

So what does this mean?

Durdu
  • 4,649
  • 2
  • 27
  • 47
RjC
  • 827
  • 2
  • 14
  • 33
  • Note: This is using *trailing closure syntax*. The closure following the call is being provided as the last argument to the call. Everything between `{ (response) in` and `}` is a closure which takes a `Bool` and returns nothing. This closure is given to `requestAccess` as `completionHandler` and when the function calls `completionHandler(true)` or maybe with `false` your closure will will execute. – vacawama Feb 23 '18 at 14:58
  • this completion handler does not expect a response _from_ you, it will _notify_ you after the user of your app made their mind up about granting / denying permission (`Bool`) to capturing videos – and you obviously want to get a feedback about that because your app next action depends on the user's decision. – holex Feb 23 '18 at 15:29

4 Answers4

4

Read Closures section of the Swift documentation.

It is a completion closure that gets executed when the AVCaptureDevice.requestAccess is finished with requesting access from the user. It has one Bool parameter that is true/false according to whether the user granted the access or not. It is not optional, so you have to provide some closure - that was a decision of the AVCaptureDevice.requestAccess author, and it makes sense - if you are requesting the access, you are requesting it because you want to use AVCaptureDevice. Therefore the author expects you to react to completing the requestAccess in some way.

Milan Nosáľ
  • 19,169
  • 4
  • 55
  • 90
  • Thanks. I understand this now. But why can't I use the same structure as above for `PHPhotoLibrary.requestAuthorization` ? If I use "response" I get this error: **PHAuthorizationStatus' is not convertible to 'Bool'** . In that case I just use `if status == .authorized {...` . Isn't this the same structure? – RjC Feb 23 '18 at 14:52
  • @RjC simply because the `AVCaptureDevice` has closure with type `(Bool) -> Void`, and `PHPhotoLibrary` has closure with type `(PHAuthorizationStatus) -> Void`.. they accept different types, so in one case the parameter is a `Bool` value, in the other `PhAutorizationStatus` (see documentation: https://developer.apple.com/documentation/photos/phphotolibrary/1620736-requestauthorization) – Milan Nosáľ Feb 23 '18 at 14:56
  • Thanks so much! That helped a lot to understand whats going on here! – RjC Feb 23 '18 at 15:02
2

Closure expression syntax has the following general form:

{ (parameters) -> return type in
    statements
}

The parameters in closure expression syntax can be in-out parameters, but they can’t have a default value. Variadic parameters can be used if you name the variadic parameter. Tuples can also be used as parameter types and return types.

completionHandler: ((Bool) -> Void) this means that you'll get a Boolean value in your closure and it will return nothing(Void). Just like a method.

You can find this more about in Apple's documentation about closures

Agent Smith
  • 2,873
  • 17
  • 32
  • Closures have become a bigger part of iOS development(I can't speak for macOS but i'm assuming there as well). Most of the time when you see/create a closure it is because of async programming. You can think of it as the 'done' section of an ajax call, or kind of like a finally statement to a try catch. – Jacob Boyd Feb 23 '18 at 14:41
2

(Bool) -> Void means a closure take accepts a Bool as a argument and return a Void (i.e. nothing).

You provide a completion handler because requestAccess execute asynchronously. When the user has decided what permission to give your app, iOS will call the completion handler to continue execution of your program.

Code Different
  • 90,614
  • 16
  • 144
  • 163
1

The majority of closures are used to handle some information that will be available later, for instance, a back end request that will take some seconds to respond, or even some action is required before some operation.

When you call a function that has a completion handler, it's the same as asking for something in the future, that will execute when the information is available, it's a great solution for asynchronous stuff or when you need to wait for some action, and then continue when you got the necessary data.

Gustavo Vollbrecht
  • 3,188
  • 2
  • 19
  • 37