Skip to content

Fix Swift Concurrency and Sendable Warnings #240

@DrunkOnJava

Description

@DrunkOnJava

Issue Description

Multiple Swift concurrency and Sendable-related warnings and errors are preventing clean compilation in iOS 17+ with strict concurrency checking enabled.

Types of Concurrency Issues

Missing await Keywords

  • Various async function calls missing await prefix
  • Example: viewModel.monitoringManager.initialize(with: .granted) should be await viewModel.monitoringManager.initialize(with: .granted)

Actor Isolation Issues

  • Call to actor-isolated instance method 'breaker(...)' in a synchronous nonisolated context
  • Accessing actor-isolated members from non-actor contexts

Non-Sendable Type Issues

  • static property 'shared' is not concurrency-safe because non-'Sendable' type 'AccessibilityAnnouncementManager' may have shared mutable state
  • non-sendable parameter type 'Self.Entity.ID' cannot be sent from caller of protocol requirement 'fetch(id:)' into actor-isolated implementation
  • capture of 'self' with non-sendable type ... in a '@Sendable' closure

MainActor Isolation Issues

  • main actor-isolated default value in a nonisolated context
  • UI-related classes need proper @mainactor annotation

Affected Classes

  • AccessibilityAnnouncementManager
  • DefaultSoundFeedbackService
  • SoundFeedbackService (protocol)
  • Various ViewModel classes
  • Repository implementations
  • Network and storage services

Solution Plan

1. Add @mainactor to UI-Related Classes

@MainActor
public final class AccessibilityAnnouncementManager {
    public static let shared = AccessibilityAnnouncementManager()
    // ...
}

@MainActor  
public final class DefaultSoundFeedbackService: SoundFeedbackService {
    // ...
}

2. Make Types Sendable

public struct TelemetryData: Codable, Sendable {
    // ...
}

public struct InventoryItem: Codable, Identifiable, Hashable, Sendable {
    // ...
}

3. Use nonisolated for Protocol Methods

public final class DefaultSoundFeedbackService: SoundFeedbackService {
    nonisolated public func playSuccessSound() { /* ... */ }
    nonisolated public func playErrorSound() { /* ... */ }
    nonisolated public func playHapticFeedback(_ type: HapticFeedbackType) { /* ... */ }
}

4. Add @preconcurrency for Legacy Protocols

public final class DefaultSoundFeedbackService: @preconcurrency SoundFeedbackService {
    // ...
}

5. Wrap Async Calls in Tasks

// Instead of: reachability.startNotifier()
Task {
    await reachability.startNotifier()
}

6. Use Proper Closure Capture

// Use [weak self] or [unowned self] in @Sendable closures
somePublisher.sink { [weak self] value in
    // ...
}

Priority

Medium - These are warnings that don't prevent compilation but should be addressed for proper Swift 6 readiness and runtime safety.

Acceptance Criteria

  • All missing await keywords are added
  • UI-related classes are marked with @mainactor
  • Appropriate types conform to Sendable
  • Actor isolation issues are resolved
  • @sendable closure capture issues are fixed
  • nonisolated methods are properly marked
  • @preconcurrency is used where appropriate for legacy protocols

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions