Skip to content

Commit 7e96304

Browse files
author
pjechris
authored
tech(Observable) Remove observable object (#74)
1 parent 6bb6cb5 commit 7e96304

File tree

11 files changed

+63
-129
lines changed

11 files changed

+63
-129
lines changed

.editorconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
root = true
2+
3+
[*]
4+
end_of_line = lf
5+
trim_trailing_whitespace = true
6+
7+
# 4 space indentation
8+
[*.swift]
9+
indent_style = space
10+
indent_size = 4

Sources/CohesionKit/EntityStore.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ extension EntityStore {
254254
@discardableResult
255255
public func update<T: Identifiable>(_ type: T.Type, id: T.ID, modifiedAt: Stamp? = nil, update: Update<T>) -> Bool {
256256
transaction {
257-
guard var entity = storage[T.self, id: id]?.ref.value else {
257+
guard var entity = storage[T.self, id: id]?.value else {
258258
return false
259259
}
260260

@@ -275,7 +275,7 @@ extension EntityStore {
275275
@discardableResult
276276
public func update<T: Aggregate>(_ type: T.Type, id: T.ID, modifiedAt: Stamp? = nil, _ update: Update<T>) -> Bool {
277277
transaction {
278-
guard var entity = storage[T.self, id: id]?.ref.value else {
278+
guard var entity = storage[T.self, id: id]?.value else {
279279
return false
280280
}
281281

@@ -294,7 +294,7 @@ extension EntityStore {
294294
@discardableResult
295295
public func update<T: Identifiable>(named: AliasKey<T>, modifiedAt: Stamp? = nil, update: Update<T>) -> Bool {
296296
transaction {
297-
guard let aliasNode = refAliases[named], var content = aliasNode.ref.value.content else {
297+
guard let aliasNode = refAliases[named], var content = aliasNode.value.content else {
298298
return false
299299
}
300300

@@ -313,7 +313,7 @@ extension EntityStore {
313313
@discardableResult
314314
public func update<T: Aggregate>(named: AliasKey<T>, modifiedAt: Stamp? = nil, update: Update<T>) -> Bool {
315315
transaction {
316-
guard let aliasNode = refAliases[named], var content = aliasNode.ref.value.content else {
316+
guard let aliasNode = refAliases[named], var content = aliasNode.value.content else {
317317
return false
318318
}
319319

@@ -333,7 +333,7 @@ extension EntityStore {
333333
public func update<C: Collection>(named: AliasKey<C>, modifiedAt: Stamp? = nil, update: Update<C>)
334334
-> Bool where C.Element: Identifiable {
335335
transaction {
336-
guard let aliasNode = refAliases[named], var content = aliasNode.ref.value.content else {
336+
guard let aliasNode = refAliases[named], var content = aliasNode.value.content else {
337337
return false
338338
}
339339

@@ -353,7 +353,7 @@ extension EntityStore {
353353
public func update<C: Collection>(named: AliasKey<C>, modifiedAt: Stamp? = nil, update: Update<C>)
354354
-> Bool where C.Element: Aggregate {
355355
transaction {
356-
guard let aliasNode = refAliases[named], var content = aliasNode.ref.value.content else {
356+
guard let aliasNode = refAliases[named], var content = aliasNode.value.content else {
357357
return false
358358
}
359359

Sources/CohesionKit/Observer/EntityObserver.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@ public struct EntityObserver<T> {
99
let createObserver: (@escaping OnChange) -> Subscription
1010

1111
init(node: EntityNode<T>, registry: ObserverRegistry) {
12-
self.value = node.ref.value
12+
self.value = node.value
1313
self.createObserver = { onChange in
1414
registry.addObserver(node: node, initial: true, onChange: onChange)
1515
}
1616
}
1717

1818
init<Element>(nodes: [EntityNode<Element>], registry: ObserverRegistry) where T == [Element] {
19-
self.value = nodes.map(\.ref.value)
19+
self.value = nodes.map(\.value)
2020
self.createObserver = { onChange in
2121
registry.addObserver(nodes: nodes, initial: true, onChange: onChange)
2222
}
2323
}
2424

2525
init<Wrapped>(alias node: EntityNode<AliasContainer<Wrapped>>, registry: ObserverRegistry)
2626
where T == Optional<Wrapped> {
27-
self.init(value: node.ref.value.content) { onChange in
27+
self.init(value: node.value.content) { onChange in
2828
registry.addObserver(node: node, initial: true, onChange: { container in
2929
onChange(container.content)
3030
})

Sources/CohesionKit/Observer/Observable.swift

Lines changed: 0 additions & 50 deletions
This file was deleted.

Sources/CohesionKit/Observer/ObserverRegistry.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ class ObserverRegistry {
3636
/// register an observer to observe changes on an entity node. Everytime `ObserverRegistry` is notified about changes
3737
/// to this node `onChange` will be called.
3838
func addObserver<T>(node: EntityNode<T>, key: ObjectKey, initial: Bool = false, onChange: @escaping (T) -> Void) -> Subscription {
39-
let handler = Handler { onChange($0.ref.value) }
39+
let handler = Handler { onChange($0.value) }
4040

4141
if initial {
4242
if queue == DispatchQueue.main && Thread.isMainThread {
43-
onChange(node.ref.value)
43+
onChange(node.value)
4444
}
4545
else {
4646
queue.sync {
47-
onChange(node.ref.value)
47+
onChange(node.value)
4848
}
4949
}
5050
}
@@ -57,16 +57,16 @@ class ObserverRegistry {
5757
func addObserver<T>(nodes: [EntityNode<T>], initial: Bool = false, onChange: @escaping ([T]) -> Void) -> Subscription {
5858
let handler = Handler { (_: EntityNode<T>) in
5959
// use last value from nodes
60-
onChange(nodes.map(\.ref.value))
60+
onChange(nodes.map(\.value))
6161
}
6262

6363
if initial {
6464
if queue == DispatchQueue.main && Thread.isMainThread {
65-
onChange(nodes.map(\.ref.value))
65+
onChange(nodes.map(\.value))
6666
}
6767
else {
6868
queue.sync {
69-
onChange(nodes.map(\.ref.value))
69+
onChange(nodes.map(\.value))
7070
}
7171
}
7272
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import Foundation
2+
3+
public class Subscription {
4+
public let unsubscribe: () -> Void
5+
6+
init(unsubscribe: @escaping () -> Void) {
7+
var unsubscribed = false
8+
9+
self.unsubscribe = {
10+
if !unsubscribed {
11+
unsubscribe()
12+
}
13+
14+
unsubscribed = true
15+
}
16+
}
17+
18+
deinit {
19+
unsubscribe()
20+
}
21+
}

Sources/CohesionKit/Storage/EntityNode.swift

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ struct EntityMetadata {
2424
protocol AnyEntityNode: AnyObject {
2525
associatedtype Value
2626

27-
var ref: Observable<Value> { get }
28-
var value: Any { get }
27+
var value: Value { get }
2928
var metadata: EntityMetadata { get }
3029
var storageKey: String { get }
3130

@@ -47,34 +46,28 @@ class EntityNode<T>: AnyEntityNode {
4746
let node: any AnyEntityNode
4847
}
4948

50-
var value: Any { ref.value }
49+
private(set) var value: Value
5150

5251
var metadata = EntityMetadata()
5352
// FIXME: to delete, it's "just" to have a strong ref and avoid nodes to be deleted. Need a better memory management
5453
private var childrenNodes: [any AnyEntityNode] = []
5554

5655
var applyChildrenChanges = true
57-
/// An observable entity reference
58-
let ref: Observable<T>
5956

6057
let storageKey: String
6158

62-
/// last time the ref.value was changed. Any subsequent change must have a higher value to be applied
59+
/// last time `value` was changed. Any subsequent change must have a higher value to be applied
6360
/// if nil ref has no stamp and any change will be accepted
6461
private var modifiedAt: Stamp?
6562
/// entity children
6663
private(set) var children: [PartialKeyPath<T>: SubscribedChild] = [:]
6764

68-
init(ref: Observable<T>, key: String, modifiedAt: Stamp?) {
69-
self.ref = ref
65+
init(_ entity: T, key: String, modifiedAt: Stamp?) {
66+
self.value = entity
7067
self.modifiedAt = modifiedAt
7168
self.storageKey = key
7269
}
7370

74-
convenience init(_ entity: T, key: String, modifiedAt: Stamp?) {
75-
self.init(ref: Observable(value: entity), key: key, modifiedAt: modifiedAt)
76-
}
77-
7871
convenience init(_ entity: T, modifiedAt: Stamp?) where T: Identifiable {
7972
let key = "\(T.self)-\(entity.id)"
8073
self.init(entity, key: key, modifiedAt: modifiedAt)
@@ -89,11 +82,11 @@ class EntityNode<T>: AnyEntityNode {
8982
}
9083

9184
modifiedAt = newModifiedAt ?? modifiedAt
92-
ref.value = newEntity
85+
value = newEntity
9386
}
9487

9588
func nullify() -> Bool {
96-
if let value = ref.value as? Nullable {
89+
if let value = value as? Nullable {
9790
do {
9891
try updateEntity(value.nullified() as! T, modifiedAt: nil)
9992
return true
@@ -126,12 +119,12 @@ class EntityNode<T>: AnyEntityNode {
126119
}
127120

128121
if let writableKeyPath = keyPath as? WritableKeyPath<T, U.Value> {
129-
ref.value[keyPath: writableKeyPath] = child.ref.value
122+
value[keyPath: writableKeyPath] = child.value
130123
return
131124
}
132125

133126
if let optionalWritableKeyPath = keyPath as? WritableKeyPath<T, U.Value?> {
134-
ref.value[keyPath: optionalWritableKeyPath] = child.ref.value
127+
value[keyPath: optionalWritableKeyPath] = child.value
135128
return
136129
}
137130

Tests/CohesionKitTests/Observer/Stub/ObserverRegistryStub.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class ObserverRegistryStub: ObserverRegistry {
1313
}
1414

1515
func hasPendingChange<T: Equatable>(for entity: T) -> Bool {
16-
pendingChangesStub.contains { ($0 as? EntityNode<T>)?.ref.value == entity }
16+
pendingChangesStub.contains { ($0 as? EntityNode<T>)?.value == entity }
1717
}
1818

1919
func hasPendingChange<T>(for _: T.Type) -> Bool {
@@ -22,7 +22,7 @@ class ObserverRegistryStub: ObserverRegistry {
2222

2323
/// number of times change has been inserted for this entity
2424
func pendingChangeCount<T: Equatable>(for entity: T) -> Int {
25-
pendingChangesStub.filter { ($0 as? EntityNode<T>)?.ref.value == entity }.count
25+
pendingChangesStub.filter { ($0 as? EntityNode<T>)?.value == entity }.count
2626
}
2727

2828
func clearPendingChangesStub() {

Tests/CohesionKitTests/RefTests.swift

Lines changed: 0 additions & 40 deletions
This file was deleted.

Tests/CohesionKitTests/Storage/AliasStorageTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class AliasStorageTests: XCTestCase {
66
var storage: AliasStorage = [:]
77

88
XCTAssertNotNil(storage[safe: .testCollection])
9-
XCTAssertNil(storage[safe: .testCollection].ref.value.content)
9+
XCTAssertNil(storage[safe: .testCollection].value.content)
1010
}
1111

1212
func test_subscriptGet_aliasHasSameNameThanAnotherType_itReturnsAliasContainer() {

Tests/CohesionKitTests/Storage/EntityNodeTests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,27 @@ class EntityNodeTests: XCTestCase {
3030
try node.updateEntity(newEntity, modifiedAt: startTimestamp)
3131
)
3232

33-
XCTAssertEqual(node.value as? RootFixture, startEntity)
33+
XCTAssertEqual(node.value, startEntity)
3434
}
3535

3636
func test_updateEntity_stampIsSup_entityIsUpdated() throws {
3737
try node.updateEntity(newEntity, modifiedAt: startTimestamp + 1)
3838

39-
XCTAssertEqual(node.value as? RootFixture, newEntity)
39+
XCTAssertEqual(node.value, newEntity)
4040
}
4141

4242
func test_updateEntity_stampIsInf_entityIsNotUpdated() throws {
4343
XCTAssertThrowsError(
4444
try node.updateEntity(newEntity, modifiedAt: startTimestamp - 1)
4545
)
4646

47-
XCTAssertEqual(node.value as? RootFixture, startEntity)
47+
XCTAssertEqual(node.value, startEntity)
4848
}
4949

5050
func test_updateEntity_stampIsNil_entityIsUpdated() throws {
5151
try node.updateEntity(newEntity, modifiedAt: nil)
5252

53-
XCTAssertEqual(node.value as? RootFixture, newEntity)
53+
XCTAssertEqual(node.value, newEntity)
5454
}
5555

5656
func test_updateEntity_stampIsNil_stampIsNotUpdated() throws {
@@ -94,7 +94,7 @@ class EntityNodeTests: XCTestCase {
9494

9595
node.updateEntityRelationship(childNode)
9696

97-
XCTAssertEqual(node.ref.value.singleNode, newChild)
97+
XCTAssertEqual(node.value.singleNode, newChild)
9898
}
9999

100100
func test_observeChild_childIsCollection_eachChildIsAdded() {

0 commit comments

Comments
 (0)