Skip to content

Commit

Permalink
UIKit binding internals refactoring (#10)
Browse files Browse the repository at this point in the history
* simplified Presenter

* minor API improvements

* moved presenter

* minor fix

* simplified presenter

* updated ref cycle test
  • Loading branch information
KazaiMazai authored Mar 31, 2024
1 parent 29f76cf commit fcb9932
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 142 deletions.
46 changes: 31 additions & 15 deletions Sources/Puredux/UIKit/Presentable.swift
Original file line number Diff line number Diff line change
@@ -1,39 +1,55 @@
//
// File.swift
//
//
//
// Created by Sergey Kazakov on 02.12.2020.
//



import Dispatch

public protocol PresenterProtocol {
func subscribeToStore()
}

public protocol Presentable: AnyObject {
associatedtype Props

var presenter: PresenterProtocol? { get set }

func setProps(_ props: Props)
}

public extension Presentable {

func with<State, Action>(store: Store<State, Action>,
props: @escaping (State, Store<State, Action>) -> Self.Props,
presentationQueue: PresentationQueue = .sharedPresentationQueue,
removeStateDuplicates equating: Equating<State> = .neverEqual) {

let presenter = Presenter(
viewController: self,
store: store,
props: props,
presentationQueue: presentationQueue,
removeStateDuplicates: equating.predicate)
removeStateDuplicates equating: Equating<State>? = nil) {

let weakStore = store.store()
let observer = Observer(
self,
removeStateDuplicates: equating,
observe: { [weak self] state, complete in
presentationQueue.dispatchQueue.async {
let props = props(state, weakStore)

PresentationQueue.main.dispatchQueue.async { [weak self] in
self?.setProps(props)
complete(.active)
}
}
}
)

presenter = Presenter { store.subscribe(observer: observer) }
}
}

self.presenter = presenter
struct Presenter: PresenterProtocol {
let subscribe: () -> Void

func subscribeToStore() {
subscribe()
}
}

93 changes: 0 additions & 93 deletions Sources/Puredux/UIKit/Presenter.swift

This file was deleted.

4 changes: 0 additions & 4 deletions Tests/PureduxTests/TestUtils/TestState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,4 @@ class ReferenceTypeState {
func reduce(_ action: Action) {

}

deinit {

}
}
Original file line number Diff line number Diff line change
@@ -1,76 +1,76 @@
//
// File.swift
//
//
//
// Created by Sergey Kazakov on 06.03.2023.
//

import XCTest
@testable import Puredux


final class ChildStorePresenterRefCycleTests: XCTestCase {
let timeout: TimeInterval = 4

let state = TestAppStateWithIndex()

lazy var factory: StoreFactory = {
StoreFactory<TestAppStateWithIndex, Action>(
initialState: state,
reducer: { state, action in
state.reduce(action)
})
}()

func test_WhenStrongRefToVC_ThenStrongRefToChildStore() {
func test_WhenStrongRefToVC_ThenStrongRefToChildStoreState() {
var strongViewController: StubViewController?
weak var weakRefObject: ReferenceTypeState?

autoreleasepool {
let strongRefObject = ReferenceTypeState()
let object = ReferenceTypeState()

let strongChildStore = factory.childStore(
initialState: strongRefObject,
let store = factory.childStore(
initialState: object,
reducer: { state, action in state.reduce(action) }
)

weakRefObject = strongRefObject

weakRefObject = object
let viewController = StubViewController()

viewController.with(store: strongChildStore,
props: { state, _ in .init(title: "") }
viewController.with(store: store,
props: { _, _ in .init(title: "") }
)

viewController.viewDidLoad()
strongViewController = viewController
}

XCTAssertNotNil(weakRefObject)
}

func test_WhenNoStrongRefToVC_ThenChildStoreIsReleased() {
func test_WhenNoStrongRefToVC_ThenChildStoreStateIsReleased() {
weak var weakRefObject: ReferenceTypeState?
var strongViewController: StubViewController?

autoreleasepool {
let strongRefObject = ReferenceTypeState()
let object = ReferenceTypeState()

let strongChildStore = factory.childStore(
initialState: strongRefObject,
let store = factory.childStore(
initialState: object,
reducer: { state, action in state.reduce(action) }
)

weakRefObject = strongRefObject

weakRefObject = object
let viewController = StubViewController()

viewController.with(store: strongChildStore,
props: { state, _ in .init(title: "") }
viewController.with(store: store,
props: { _, _ in .init(title: "") }
)

viewController.viewDidLoad()
strongViewController = viewController
}


XCTAssertNotNil(weakRefObject)
strongViewController = nil
XCTAssertNil(weakRefObject)
}
Expand Down

0 comments on commit fcb9932

Please sign in to comment.