mirror of
https://github.com/RevenueCat/purchases-ios
synced 2026-11-11 22:55:55 +05:45
For [CSDK-379]. Extracted #1795 to make it easier to review this fix in isolation. `handleUserDefaultsChanged` isn't guaranteed to be called from any particular thread, so its access to `appUserIDHasBeenSet` wasn't thread-safe. This is now guaranteed by `Sendable`. _In theory. In practice we are required to use `@unchecked` for now because of `NotificationCenter` and the class not being `final`. But without those I verified that the class does compile with `Sendable`, which means that there aren't any other potential issues._ [CSDK-379]: https://revenuecats.atlassian.net/browse/CSDK-379?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
50 lines
1.5 KiB
Swift
50 lines
1.5 KiB
Swift
//
|
|
// Copyright RevenueCat Inc. All Rights Reserved.
|
|
//
|
|
// Licensed under the MIT License (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://opensource.org/licenses/MIT
|
|
//
|
|
// SynchronizedUserDefaults.swift
|
|
//
|
|
// Created by Nacho Soto on 11/20/21.
|
|
|
|
import Foundation
|
|
|
|
/// A `UserDefaults` wrapper to synchronize access and writes.
|
|
///
|
|
/// - SeeAlso: `Atomic`.
|
|
internal final class SynchronizedUserDefaults {
|
|
|
|
private let atomic: Atomic<UserDefaults>
|
|
|
|
init(userDefaults: UserDefaults) {
|
|
self.atomic = .init(userDefaults)
|
|
}
|
|
|
|
func read<T>(_ action: (UserDefaults) throws -> T) rethrows -> T {
|
|
return try self.atomic.withValue {
|
|
return try action($0)
|
|
}
|
|
}
|
|
|
|
func write(_ action: (UserDefaults) throws -> Void) rethrows {
|
|
return try self.atomic.withValue {
|
|
try action($0)
|
|
|
|
// While Apple states `this method is unnecessary and shouldn't be used`
|
|
// https://developer.apple.com/documentation/foundation/userdefaults/1414005-synchronize
|
|
// It didn't become unnecessary until iOS 12 and macOS 10.14 (Mojave):
|
|
// https://developer.apple.com/documentation/macos-release-notes/foundation-release-notes
|
|
// there are reports it is still needed if you save to defaults then immediately kill the app.
|
|
// Also, it has not been marked deprecated... yet.
|
|
$0.synchronize()
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
extension SynchronizedUserDefaults: Sendable {}
|