3

It just converted my small Swift project to Swift 3.

Here is a compiler error that I don't understand:

var onLoadedClosures: [() -> ()] = []
open func onLoaded(closure: () -> ()) {
    onLoadedClosures += [closure]
}

Cannot convert value of type '[() -> ()]' to expected argument type 'inout _'.

I added the inout keyword:

    open func onLoaded(closure: inout () -> ()) {
        onLoadedClosures += [closure]
    }

Then it works. But why does adding an element to an array require the inout keyword? Although I know what inout means.

Hamish
  • 78,605
  • 19
  • 187
  • 280
NathanVss
  • 634
  • 5
  • 16

1 Answers1

3

It's a confusing error message – the problem is that you need to mark your closure: parameter as @escaping in order to allow it to escape the lifetime of the function onLoaded(closure:) (as per SE-0103, closure function arguments are now non-escaping by default).

var onLoadedClosures: [() -> ()] = []
open func onLoaded(closure: @escaping () -> ()) {
    onLoadedClosures += [closure]
}

The reason it works when you mark the parameter as inout is because inout closures are escaping by definition (as their value get written back to the caller upon the function exiting). However in this case there is simply no need for an inout parameter.

For more information about @escaping, see the Swift evolution proposal on the change, as well as this relevant Q&A.

Community
  • 1
  • 1
Hamish
  • 78,605
  • 19
  • 187
  • 280