Skip to content

Commit

Permalink
Remove _onUpdate from on change modifier
Browse files Browse the repository at this point in the history
  • Loading branch information
Szymon Lorenz committed Sep 10, 2023
1 parent cb0818a commit cf86cbf
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 29 deletions.
29 changes: 10 additions & 19 deletions Sources/TokamakCore/Modifiers/OnChangeModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,30 @@
//

import Foundation
import OpenCombineShim

struct OnChangeModifier<V: Equatable>: ViewModifier {
@State
var oldValue: V? = nil
private var oldValue: V?

let value: V
let initial: Bool
let action: (V, V) -> ()

init(value: V, initial: Bool, action: @escaping (V, V) -> ()) {
self.value = value
self.initial = initial
self.action = action

if value != oldValue {
action(oldValue ?? value, value)
oldValue = value
}
}

func body(content: Content) -> some View {
content
.task {
if initial {
action(value, value)
.onReceive(Just(value)) { newValue in
// TODO: Fix, when @State if working with in a ViewModifier
// ignore first call when oldValue == nil. For now old value is always nil
if newValue != oldValue {
action(oldValue ?? value, newValue)
}
oldValue = value
}
._onUpdate {
if value != oldValue {
action(oldValue ?? value, value)
.onAppear {
if initial {
action(value, value)
}
oldValue = value
}
}
}
Expand Down
24 changes: 18 additions & 6 deletions Sources/TokamakCore/Modifiers/OnReceiveModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,29 @@
import Foundation
import OpenCombineShim

struct OnReceiveModifier<P: Publisher>: ViewModifier where P.Failure == Never {
@State
var cancellable: AnyCancellable
private struct OnReceiveModifier<P: Publisher>: ViewModifier where P.Failure == Never {
@ObservedObject
var cancellableHolder = CancellableHolder()

init(publisher: P, action: @escaping (P.Output) -> ()) {
_cancellable = State(initialValue: publisher.sink(receiveValue: action))
cancellableHolder.cancellable = publisher.sink(receiveValue: action)
}

func body(content: Content) -> some View {
content.onDisappear {
cancellable.cancel()
content
}

// MARK: Types

final class CancellableHolder: ObservableObject {
var cancellable: AnyCancellable? {
didSet {
oldValue?.cancel()
}
}

deinit {
cancellable?.cancel()
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions Tests/TokamakTests/ViewReactToDataChangesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ class ViewModifierTests: XCTestCase {

// Simulate publisher emitting a value
publisher.send("Testing onReceive")

// Re-evaluate the view
let reconciler = TestFiberRenderer(.root, size: .zero).render(contentView)

XCTAssertEqual(receivedValue, "Testing onReceive")

// Simulate publisher emitting a value
publisher.send("Second onReceive")
XCTAssertEqual(receivedValue, "Second onReceive")
}

func testOnChangeWithValue() {
Expand Down

0 comments on commit cf86cbf

Please sign in to comment.