Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

189
Vistas
Pasar una estructura mutable local a un enlace let asíncrono

Quiero crear una solicitud de URL y pasarla a un enlace let asíncrono, lo que me parece natural:

 func test() async { // Force unwraps (!) are just for demo var request = URLRequest(url: URL(string:"https://stackoverflow.com")!) request.httpMethod = "GET" // just for example // some more tinkering with `request` here. // 🔴 Error on this line: "Reference to captured var 'request' in concurrently-executing code" async let responseData = URLSession.shared.data(for: request).0 // It works like this: // let immutableRequest = request // async let responseData = URLSession.shared.data(for: immutableRequest).0 // other stuff print("Response body: \(String(data: try! await responseData, encoding: .utf8))") }

¿Por qué recibo un error? URLRequest es una estructura, por lo que cuando la pasamos a una función, la función debe obtener una copia de esa estructura, por lo que si modifico la request después de la llamada asíncrona, no debería afectar la llamada.

Sé que la llamada se realiza de forma asíncrona, pero esperaría que capturara los parámetros en el punto de la llamada y luego continuara la ejecución como si se hubiera realizado la llamada (por lo tanto, se ha pasado una copia de la request en el punto de la llamada en data(for: request) .

Además, ¿hay alguna manera conveniente de hacerlo sin crear otra variable let y sin usar un cierre para inicializar la request , como:

 let request: URLRequest = { var result = URLRequest(url: URL(string:"https://stackoverflow.com")!) result.httpMethod = "GET" return result }()
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Como SE-0317 - async let bindings dice:

... async let es similar a let , ya que define una constante local que se inicializa mediante la expresión en el lado derecho de = . Sin embargo, difiere en que la expresión del inicializador se evalúa en una tarea secundaria independiente que se ejecuta simultáneamente.

La tarea secundaria comienza a ejecutarse tan pronto como se encuentra el async let .

...

Un async let crea una tarea secundaria, que hereda la prioridad de su tarea principal, así como los valores locales de la tarea. Semánticamente, esto es equivalente a crear un grupo de TaskGroup único que genera una sola tarea y devuelve su resultado...

De manera similar a la función [ group.addTask ], el cierre es @Sendable y nonisolated , lo que significa que no puede acceder al estado no enviable del contexto adjunto. Por ejemplo, dará como resultado un error en tiempo de compilación, lo que evitará una posible condición de carrera, para que un inicializador async let intente mutar una variable cerrada:

 var localText: [String] = ... async let w = localText.removeLast() // error: mutation of captured var 'localText' in concurrently-executing code

El inicializador async let puede referirse a cualquier estado enviable, igual que cualquier cierre enviable no aislado.

Por lo tanto, no se copia el parámetro to data(for:delegate:) y luego se crea la tarea asíncrona, sino al revés.

Por lo general, si estuviera utilizando un cierre, simplemente agregaría la request a la lista de captura del cierre, pero eso no es posible en este caso. Por ejemplo, podría crear una Task usted mismo con una lista de captura, logrando algo similar a async let , pero con mayor control:

 func test() async throws { var request = URLRequest(url: URL(string:"https://httpbin.org/get")!) request.httpMethod = "GET" // just for example let task = Task { [request] in try await URLSession.shared.data(for: request).0 } // do some more stuff in parallel print("Response body: \(String(data: try await task.value, encoding: .utf8) ?? "Not string")") }

Obviamente, puede simplemente await los data(for:delegate:) , en lugar de async let , y el problema desaparece:

 func test() async throws { var request = URLRequest(url: URL(string:"https://httpbin.org/get")!) request.httpMethod = "GET" // just for example let data = try await URLSession.shared.data(for: request).0 print("Response body: \(String(data: data, encoding: .utf8) ?? "Not string")") }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda