I’m trying to migrate my (tiny) macOS and iOS app to Swift 6.
I have the following singleton SettingsManager
class:
final class SettingsManager: ObservableObject {
static let shared = SettingsManager()
private init() {}
@AppStorage("showTimeLeft") var showTimeLeft = true
@AppStorage("hideAppOnTimerStart") var hideAppOnTimerStart = false
// More settings here
}
This class is used in different places throughout my app, as in the following pseudocode:
if SettingsManager.shared.showTimeLeft {
Text("Time left here")
}
What is the proper way of migrating this class to Swift 6? I’m currently getting the following error:
Static property ‘shared’ is not concurrency-safe because non-‘Sendable’ type ‘SettingsManager’ may have shared mutable state
Xcode gives me three options:
- Class ‘SettingsManager’ does not conform to the ‘Sendable’ protocol
- Annotate ‘shared’ with ‘@MainActor’ if property should only be accessed from the main actor
- Disable concurrency-safety checks if accesses are protected by an external synchronization mechanism
The first option (making SettingsManager conform to Sendable) gives me a new error: “Stored property ‘_showTimeLeft’ of ‘Sendable’-conforming class ‘SettingsManager’ is mutable”
Annotating the entire class with @MainActor works in so far as it removes all errors, but is this consider good practice? I don’t yet know much about Swift, but my belief is that @MainActor is primarily intended for UI code? I may be wrong about that, however.
The third option, I think, does not apply here.
P.S.: I don’t really know what I’m doing, and it’s entirely possible this singleton pattern is a terrible idea in general — just let me know if that’s the case.
3