YunoPaymentDelegate, YunoEnrollmentDelegate). This section explains the challenges and provides solutions for different implementation scenarios.
Understanding Concurrency in Swift 6Concurrency is the ability of your app to manage multiple tasks simultaneously. With Swift 6, concurrency rules have become more stringent to enhance app stability and prevent crashes.
The problem
With Swift 6, protocols that inherit fromSendable require all their implementations to be thread-safe. This generates warnings when implementing the delegate in classes marked as @MainActor.
Thread-safe means your code can be safely called from multiple threads without causing crashes or unexpected behavior. @MainActor ensures code runs on the main thread (UI thread).
Our design decision
We do not mark protocols as@MainActor because:
- It would force all implementations to be
MainActorcompatible - It would reduce flexibility for merchants who don’t use
MainActor - Each implementation has different concurrency needs
Merchant’s responsibility
It’s the merchant’s responsibility to handle concurrency according to their implementation. Below are three different approaches you can use depending on your specific needs.Option 1: Immutable properties
This approach uses immutable properties that are automatically thread-safe, making them ideal for simple configurations. It is best suited for simple apps with fixed configuration values that don’t change during runtime.Option 2: Mutable properties with MainActor.assumeIsolated
This approach, best for apps where configuration values might change during runtime (like user preferences), allows for mutable properties while maintaining thread safety by using MainActor.assumeIsolated.
Option 3: For non MainActor classes
This approach is suitable for service classes that don’t require MainActor isolation, making it best for background services or utility classes that don’t interact with the UI.
The examples above use
YunoPaymentDelegate, but the same principles apply to YunoEnrollmentDelegate. You should use customerSession instead of checkoutSession when implementing the enrollment delegate.Important considerations
When implementing concurrency in your delegate, keep these key points in mind:MainActor.assumeIsolated: Only use when you guarantee it’s called fromMainActor. This is a safety mechanism that tells Swift “trust me, I know this is running on the main thread.”nonisolated: Means it can be accessed from any thread, so it must be thread-safe. Use this when your properties or methods don’t depend on UI state.viewController: Remains as@MainActorbecause it should always be accessed from the main thread. UI components must always run on the main thread to prevent crashes.