Overview › Swift Concurrency
Swift Concurrency
async/await adopted in newer modules; legacy completion handlers + DispatchQueue dominate.
72
SCORE
Summary
The project supports Swift Concurrency (async/await) — newer SPM packages adopt it — but legacy code relies heavily on Grand Central Dispatch and completion handlers. 40+ DispatchQueue.main.asyncAfter calls observed without DispatchWorkItem for cancellation.
Findings
PASS
async/await adopted in newer features
Newer SPM packages use
async functions and Task. CostcoNetworkClient supports async API alongside completion handlers.HIGH
asyncAfter without cancellation
40+ instances of
DispatchQueue.main.asyncAfter with closures that capture self strongly. Stale callbacks fire after view dismissal and can crash or trigger duplicated state changes.Recommendation: Use
DispatchWorkItem stored on the view controller; call cancel() in viewWillDisappear. Or replace with Task + Task.cancel.HIGH
Strong-self capture in escaping closures
Many completion-handler closures don't use
[weak self] or [unowned self]. Combined with long-lived references (NotificationCenter, Timer), retain cycles are likely.Recommendation: SwiftLint rule for closure capture; require
[weak self] in escaping closures stored on long-lived objects.MEDIUM
DispatchQueue.main.sync deadlock risk
Calling
main.sync from the main thread deadlocks the app. Audit any main.sync usage.Recommendation: Replace with
main.async or restructure caller to be on a background queue.LOW
Combine + async/await dual world
Some code uses Combine publishers, others use AsyncSequence. Pick a primary pattern per feature to avoid bridging boilerplate.
Recommendation: Document a default — likely async/await + AsyncSequence for new code; let Combine remain only where deeply integrated.
Findings in this category
Costco iOS · Code Review Report · Generated 2026-05-07 · 88 machine-curated findings