peroseth
peroseth

Reputation: 83

Closure use of non-escaping parameter - Swift 3 issue

I know about the changes in Swift 3 where @nonescaping is default behaviour for closures.

I have successfully changed much of my code regarding the changes but I have one part of my code where I am not able to get rid of the Closure use of non-escaping parameter may allow it to escape compilation error.

I have tried adding @escaping to both the updateHandler parameter and the UpdatedInProgressHandler typealias but it does not seem to be enough.

Anyone able to help me figuring out the reason for my problem?

The code where typealiases and the function is defined:

// Typealiases used to clean up closures
typealias UpdateInProgressCompletion = () -> ()
typealias UpdateInProgressCancelCompletion = () -> ()
typealias UpdateInProgressHandler = ((_ completed: @escaping UpdateInProgressCompletion) -> ()) -> ()

// Method for wrapping the presentation and dismissal of the custom alert controller
func presentUpdateInProgress(_ taskIdentifier: String?, alertMessage: String?, alertHeader: String? = nil, updateHandler: @escaping UpdateInProgressHandler, cancel cancelHandler: UpdateInProgressCancelCompletion? = nil) {

    let updateInProgressAlert = self.updateInProgressAlert( taskIdentifier, alertMessage: alertMessage, alertHeader: alertHeader ) { action in
        cancelHandler?()
        Logger.debug("User cancelled update")
    }

    updateInProgressAlert.present(completion: nil)

    updateHandler { (completion) in
        updateInProgressAlert.dismiss(completion: completion)
    }
}

The code where I get the "Closure use of non-escaping parameter "updateCompleted" may allow if to escape" error when calling presentUpdateInProgress function.

    self.presentUpdateInProgress(taskIdentifier, alertMessage: "My alert message", updateHandler: { (updateCompleted) -> () in

        let task = CreateModelTask(completionHandler: { (resultObject) -> () in
            updateCompleted { // this generates the error

                //Do some stuff with received result
            }
        })

        task.taskIdentifier = taskIdentifier
        SyncManager.sharedManager.addTaskToQueue(task)
    })

Upvotes: 4

Views: 2665

Answers (1)

Hamish
Hamish

Reputation: 80951

updateCompleted is of type (_ completed: @escaping UpdateInProgressCompletion) -> (), which as it's a function parameter itself, means that it is non-escaping by default (note that 'non-escaping by default' behaviour is only applicable to function closure arguments, see this Q&A, as well as its dupe target on the topic).

Therefore in order to allow updateCompleted to escape, you need to mark (_ completed: @escaping UpdateInProgressCompletion) -> () as @escaping in your typealias:

typealias UpdateInProgressHandler = (@escaping (_ completed: @escaping UpdateInProgressCompletion) -> ()) -> ()

Upvotes: 3

Related Questions