Skip to content

Commit

Permalink
Fix crash when cancelling subscription for custom PersistenceKey (#3494)
Browse files Browse the repository at this point in the history
* Add crashing unit test for AppStorageKey subscription cancellation

* Fix double cancellation of Shared.Subscription
  • Loading branch information
pyrtsa authored Nov 14, 2024
1 parent 333aa22 commit 69247ba
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ extension Shared {
/// This object is returned from ``PersistenceReaderKey/subscribe(initialValue:didSet:)``, which
/// will feed updates from an external system for its lifetime, or till ``cancel()`` is called.
public class Subscription {
let onCancel: () -> Void
var onCancel: (() -> Void)?

/// Initializes the subscription with the given cancel closure.
///
Expand All @@ -88,7 +88,8 @@ extension Shared {

/// Cancels the subscription.
public func cancel() {
self.onCancel()
self.onCancel?()
self.onCancel = nil
}
}
}
16 changes: 16 additions & 0 deletions Tests/ComposableArchitectureTests/SharedTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,22 @@ final class SharedTests: XCTestCase {
}
}
}

func testPersistenceKeySubscription() async throws {
let persistenceKey: AppStorageKey<Int> = .appStorage("shared")
let changes = LockIsolated<[Int?]>([])
var subscription: Optional = persistenceKey.subscribe(initialValue: nil) { value in
changes.withValue { $0.append(value) }
}
@Dependency(\.defaultAppStorage) var userDefaults
userDefaults.set(1, forKey: "shared")
userDefaults.set(42, forKey: "shared")
subscription?.cancel()
userDefaults.set(123, forKey: "shared")
subscription = nil
XCTAssertEqual([1, 42], changes.value)
XCTAssertEqual(123, persistenceKey.load(initialValue: nil))
}
}

@globalActor actor GA: GlobalActor {
Expand Down

0 comments on commit 69247ba

Please sign in to comment.