File tree Expand file tree Collapse file tree 5 files changed +91
-9
lines changed
Expand file tree Collapse file tree 5 files changed +91
-9
lines changed Original file line number Diff line number Diff line change @@ -349,25 +349,54 @@ extension EntityStore {
349349extension EntityStore {
350350 /// Removes an alias from the storage
351351 public func removeAlias< T> ( named: AliasKey < T > ) {
352- refAliases [ named] = nil
353- logger? . didUnregisterAlias ( named)
352+ transaction {
353+ if let alias = refAliases [ named] {
354+ do {
355+ try alias. updateEntity ( AliasContainer ( key: named, content: nil ) , modifiedAt: nil )
356+ logger? . didUnregisterAlias ( named)
357+ }
358+ catch {
359+
360+ }
361+ }
362+ }
354363 }
355364
356365 /// Removes an alias from the storage
357366 public func removeAlias< C: Collection > ( named: AliasKey < C > ) {
358- refAliases [ named] = nil
359- logger? . didUnregisterAlias ( named)
367+ transaction {
368+ if let alias = refAliases [ named] {
369+ do {
370+ try alias. updateEntity ( AliasContainer ( key: named, content: nil ) , modifiedAt: nil )
371+ logger? . didUnregisterAlias ( named)
372+ }
373+ catch {
374+
375+ }
376+ }
377+ }
378+
360379 }
361380
362381 /// Removes all alias from identity map
363382 public func removeAllAlias( ) {
364- refAliases. removeAll ( )
383+ transaction {
384+ removeAliases ( )
385+ }
365386 }
366387
367388 /// Removes all alias AND all objects stored weakly. You should not need this method and rather use `removeAlias`.
368389 /// But this can be useful if you fear retain cycles
369390 public func removeAll( ) {
370- refAliases. removeAll ( )
371- storage. removeAll ( )
391+ transaction {
392+ removeAliases ( )
393+ storage. removeAll ( )
394+ }
395+ }
396+
397+ private func removeAliases( ) {
398+ for (_, node) in refAliases {
399+ node. nullify ( )
400+ }
372401 }
373402}
Original file line number Diff line number Diff line change @@ -68,4 +68,18 @@ extension AliasContainer: CollectionIdentifiableKeyPathsEraser where T: MutableC
6868 var erasedEntitiesKeyPaths : [ Any ] {
6969 [ PartialIdentifiableKeyPath < Self > ( \. content) ]
7070 }
71- }
71+ }
72+
73+ extension AliasContainer : Equatable where T: Equatable {
74+
75+ }
76+
77+ protocol Nullable {
78+ func nullified( ) -> Self
79+ }
80+
81+ extension AliasContainer : Nullable {
82+ func nullified( ) -> AliasContainer < T > {
83+ AliasContainer ( key: key, content: nil )
84+ }
85+ }
Original file line number Diff line number Diff line change 11/// Keep a strong reference on each aliased node
2- typealias AliasStorage = [ String : Any ]
2+ typealias AliasStorage = [ String : AnyEntityNode ]
33
44extension AliasStorage {
55 subscript< T> ( _ aliasKey: AliasKey < T > ) -> EntityNode < AliasContainer < T > > ? {
Original file line number Diff line number Diff line change @@ -4,6 +4,8 @@ import Combine
44/// Typed erased protocol
55protocol AnyEntityNode : AnyObject {
66 var value : Any { get }
7+
8+ func nullify( )
79}
810
911/// A graph node representing a entity of type `T` and its children. Anytime one of its children is updated the node
@@ -53,6 +55,12 @@ class EntityNode<T>: AnyEntityNode {
5355 onChange ? ( self )
5456 }
5557
58+ func nullify( ) {
59+ if let value = ref. value as? Nullable {
60+ try ? updateEntity ( value. nullified ( ) as! T , modifiedAt: nil )
61+ }
62+ }
63+
5664 func removeAllChildren( ) {
5765 children = [ : ]
5866 }
Original file line number Diff line number Diff line change @@ -424,6 +424,37 @@ extension EntityStoreTests {
424424 }
425425}
426426
427+ // MARK: Remove
428+ extension EntityStoreTests {
429+ func test_removeAlias_itEnqueuesNilInRegistry( ) {
430+ let registry = ObserverRegistryStub ( )
431+ let store = EntityStore ( registry: registry)
432+
433+ _ = store. store ( entity: SingleNodeFixture ( id: 1 ) , named: . test)
434+
435+ registry. clearPendingChangesStub ( )
436+
437+ store. removeAlias ( named: . test)
438+
439+ XCTAssertTrue ( registry. hasPendingChange ( for: AliasContainer ( key: . test, content: nil ) ) )
440+ }
441+
442+ func test_removeAllAlias_itEnqueuesNilForEachAlias( ) {
443+ let registry = ObserverRegistryStub ( )
444+ let store = EntityStore ( registry: registry)
445+
446+ _ = store. store ( entity: SingleNodeFixture ( id: 1 ) , named: . test)
447+ _ = store. store ( entities: [ SingleNodeFixture ( id: 2 ) ] , named: . listOfNodes)
448+
449+ registry. clearPendingChangesStub ( )
450+
451+ store. removeAllAlias ( )
452+
453+ XCTAssertTrue ( registry. hasPendingChange ( for: AliasContainer ( key: . test, content: nil ) ) )
454+ XCTAssertTrue ( registry. hasPendingChange ( for: AliasContainer ( key: . listOfNodes, content: nil ) ) )
455+ }
456+ }
457+
427458private extension AliasKey where T == SingleNodeFixture {
428459 static let test = AliasKey ( named: " test " )
429460}
You can’t perform that action at this time.
0 commit comments