Skip to content

Commit 506316b

Browse files
committed
Snapshot arrays in ImagePrefetcher.handleComplete
Mitigates a crash from iterating over sources while they are mutating. Example crash (details omitted): ``` 0 App <redacted> Source 1 App <redacted> Source 2 App <redacted> Array._getElement 3 App <redacted> Sequence.compactMap 4 App <redacted> ImagePrefetcher.handleComplete (ImagePrefetcher.swift:379) ```
1 parent f7ed0b8 commit 506316b

File tree

1 file changed

+13
-6
lines changed

1 file changed

+13
-6
lines changed

Sources/Networking/ImagePrefetcher.swift

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -370,14 +370,21 @@ public class ImagePrefetcher: CustomStringConvertible, @unchecked Sendable {
370370
if completionHandler == nil && completionSourceHandler == nil {
371371
return
372372
}
373-
373+
374+
// Snapshot arrays/handlers before switching threads to avoid concurrent mutation crashes.
375+
let skipped = self.skippedSources
376+
let failed = self.failedSources
377+
let completed = self.completedSources
378+
let completionSourceHandler = self.completionSourceHandler
379+
let completionHandler = self.completionHandler
380+
374381
// The completion handler should be called on the main thread
375382
CallbackQueue.mainCurrentOrAsync.execute {
376-
self.completionSourceHandler?(self.skippedSources, self.failedSources, self.completedSources)
377-
self.completionHandler?(
378-
self.skippedSources.compactMap { $0.asResource },
379-
self.failedSources.compactMap { $0.asResource },
380-
self.completedSources.compactMap { $0.asResource }
383+
completionSourceHandler?(skipped, failed, completed)
384+
completionHandler?(
385+
skipped.compactMap { $0.asResource },
386+
failed.compactMap { $0.asResource },
387+
completed.compactMap { $0.asResource }
381388
)
382389
self.completionHandler = nil
383390
self.progressBlock = nil

0 commit comments

Comments
 (0)