Resolving the “Closure Use of Non-Escaping Parameter May Allow It to Escape” Error in Swift

Resolving the "Closure Use of Non-Escaping Parameter May Allow It to Escape" Error in Swift

28 February 2025 Stephan Petzl Leave a comment Xcode

If you’ve encountered the “Closure use of non-escaping parameter may allow it to escape” error while working with Swift, you’re not alone. This issue arises due to changes in Swift’s handling of function-typed parameters, which can be confusing for developers transitioning from earlier versions of Swift. In this guide, we’ll explore the underlying cause of this error and provide clear solutions to resolve it.

Understanding the Error

The error occurs when a closure is used in a context where it is allowed to escape the scope of the function it was passed to. In Swift 3 and later versions, function-typed parameters are non-escaping by default. This means they cannot be stored or captured beyond the duration of the function call unless explicitly marked as @escaping.

Solution: Marking the Closure as Escaping

To resolve the error, you need to explicitly mark the closure as escaping if you intend to store or capture it beyond the immediate function call. This is particularly relevant in scenarios involving asynchronous operations, such as network requests or unit tests.

protocol DataServiceType {
  func fetchData(location: String, completion: @escaping (DataFetchResult) -> Void)
  func cachedData(location: String) -> Data?
}

func fetchData(location: String, completion: @escaping (DataFetchResult) -> Void) {
  // Your asynchronous code here
}

Alternative Approach: Optional Completion Closure

In situations where you don’t need the closure to escape, you can opt for an optional completion handler. This approach is useful when the result of the closure isn’t critical, or the context in which it’s executed might not need to persist.

func fetchData(location: String, completion: ((DataFetchResult) -> Void)?) {
  // Your code here
  completion?(self.result)
}

Practical Example in Swift 5

Recent implementations in Swift 5 have shown that making the completion block an optional variable can effectively handle this issue. This method allows for flexibility and ensures that your functions can gracefully handle scenarios where the completion closure might not be necessary.

private func updateBreakTime(for id: String, to time: Time, onSucess: EmptyAction?) {
  dataRepository.updateBreak(
      id: id,
      to: time.seconds,
      onSuccess: { _ in
          onSucess?()
      },
      onError: { [weak self] error in
          self?.screen.showError(error)
      }
  )
}

Enhancing Your Testing Workflow with Repeato

For developers looking to streamline their testing processes, Repeato offers a compelling solution. As a no-code test automation tool, Repeato simplifies the creation, execution, and maintenance of automated tests for iOS, Android, and web applications. By leveraging computer vision and AI, Repeato enables rapid test recording and execution, making it an excellent choice for handling asynchronous code and complex test scenarios. Its support for data-driven and keyword-driven testing, along with easy version control, provides a robust alternative to traditional tools like Katalon, which can be limited by scripting language constraints and resource intensiveness.

Like this article? there’s more where that came from!