Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

342
Visualizações
¿Cómo evitar que el reingreso de actores resulte en solicitudes duplicadas?

En el video de la WWDC 2021, Proteger el estado mutable con los actores de Swift , proporcionan el siguiente fragmento de código:

 actor ImageDownloader { private var cache: [URL: Image] = [:] func image(from url: URL) async throws -> Image? { if let cached = cache[url] { return cached } let image = try await downloadImage(from: url) cache[url] = cache[url, default: image] return cache[url] } func downloadImage(from url: URL) async throws -> Image { ... } }

El problema es que los actores ofrecen reingreso, por lo que la referencia de cache[url, default: image] garantiza que incluso si realizó una solicitud duplicada debido a alguna raza, al menos verifique el caché del actor después de la continuación, asegurándose de obtener la misma imagen para la solicitud duplicada.

Y en ese video dicen :

Una mejor solución sería evitar por completo las descargas redundantes. Hemos puesto esa solución en el código asociado con este video.

Pero no hay ningún código asociado con ese video en el sitio web. Entonces, ¿cuál es la mejor solución?

Entiendo los beneficios del reingreso de actores (como se discutió en SE-0306 ). Por ejemplo, si se descargan cuatro imágenes, uno no quiere prohibir la reentrada, perdiendo la concurrencia de descargas. Efectivamente, nos gustaría esperar el resultado de una solicitud previa duplicada para una imagen en particular, si la hay, y si no, iniciar una nueva imagen de downloadImage .

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Puede encontrar el código de "mejor solución" en la aplicación Developer . Abra la sesión en la aplicación Desarrollador, seleccione la pestaña Código y desplácese hasta "11:59: verifique sus suposiciones después de esperar: una mejor solución".

captura de pantalla de la aplicación Developer

La captura de pantalla es de mi iPad, pero la aplicación Developer también está disponible en iPhone, Mac y Apple TV. (Aunque no sé si la versión de Apple TV ofrece una forma de ver y copiar el código...)

Por lo que sé, el código no está disponible en el sitio web developer.apple.com, ni en la página de la sesión de la WWDC ni como parte de un proyecto de muestra.

Para la posteridad, aquí está el código de Apple. Es extremadamente similar a la de Andy Ibáñez:

 actor ImageDownloader { private enum CacheEntry { case inProgress(Task<Image, Error>) case ready(Image) } private var cache: [URL: CacheEntry] = [:] func image(from url: URL) async throws -> Image? { if let cached = cache[url] { switch cached { case .ready(let image): return image case .inProgress(let task): return try await task.value } } let task = Task { try await downloadImage(from: url) } cache[url] = .inProgress(task) do { let image = try await task.value cache[url] = .ready(image) return image } catch { cache[url] = nil throw error } } }
over 4 years ago · Santiago Trujillo Relatório

0

La clave es mantener una referencia a la Task y, si la encuentra, await su value .

Quizás:

 actor ImageDownloader { private var cache: [URL: Image] = [:] private var tasks: [URL: Task<Image, Error>] = [:] func image(from url: URL) async throws -> Image { if let image = try await tasks[url]?.value { print("found request") return image } if let cached = cache[url] { print("found cached") return cached } let task = Task { try await download(from: url) } tasks[url] = task defer { tasks[url] = nil } let image = try await task.value cache[url] = image return image } private func download(from url: URL) async throws -> Image { let (data, response) = try await URLSession.shared.data(from: url) guard let response = response as? HTTPURLResponse, 200 ..< 300 ~= response.statusCode, let image = Image(data: data) else { throw URLError(.badServerResponse) } return image } }
over 4 years ago · Santiago Trujillo Relatório

0

Después de dar con mi respuesta original , me topé con el artículo de Andy Ibáñez, Comprensión de los actores en el nuevo modelo de concurrencia , en el que no proporciona el código de Apple, pero ofrece algo inspirado en él. La idea es muy similar, pero usa una enumeración para realizar un seguimiento de las respuestas pendientes y almacenadas en caché:

 actor ImageDownloader { private enum ImageStatus { case downloading(_ task: Task<UIImage, Error>) case downloaded(_ image: UIImage) } private var cache: [URL: ImageStatus] = [:] func image(from url: URL) async throws -> UIImage { if let imageStatus = cache[url] { switch imageStatus { case .downloading(let task): return try await task.value case .downloaded(let image): return image } } let task = Task { try await downloadImage(url: url) } cache[url] = .downloading(task) do { let image = try await task.value cache[url] = .downloaded(image) return image } catch { // If an error occurs, we will evict the URL from the cache // and rethrow the original error. cache.removeValue(forKey: url) throw error } } private func downloadImage(url: URL) async throws -> UIImage { let imageRequest = URLRequest(url: url) let (data, imageResponse) = try await URLSession.shared.data(for: imageRequest) guard let image = UIImage(data: data), (imageResponse as? HTTPURLResponse)?.statusCode == 200 else { throw ImageDownloadError.badImage } return image } }
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda