Skip to content

Commit 9fe79d0

Browse files
committed
viewModel updates observable added
1 parent 71348d4 commit 9fe79d0

7 files changed

+58
-3
lines changed

Diff for: CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
# Change Log
22

33
All notable changes to this project will be documented in this file.
4+
5+
## [1.1.0](https://github.com/sinarionn/ReusableView/releases/tag/1.1.0)
6+
7+
ViewModel updates observable added.

Diff for: ReusableView.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Pod::Spec.new do |s|
33
s.name = "ReusableView"
4-
s.version = "1.0.1"
4+
s.version = "1.1.0"
55
s.summary = "Reusable and NonReusable viewModel containers"
66

77
s.homepage = "https://github.com/sinarionn/ReusableView"

Diff for: Sources/Helpers.swift

+23-1
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,34 @@ extension Reactive where Base: ReusableViewProtocol, Base: AnyObject {
3737
get {
3838
return base.reuseBag
3939
}
40-
set {
40+
nonmutating set {
4141
base.reuseBag = newValue
4242
}
4343
}
4444
}
4545

46+
extension ViewModelHolderProtocol {
47+
internal var _viewModelDidUpdate: PublishSubject<(ViewModelProtocol, DisposeBag)> {
48+
get {
49+
objc_sync_enter(self)
50+
defer { objc_sync_exit(self) }
51+
guard let existingObserver : PublishSubject<(ViewModelProtocol, DisposeBag)> = associated(with: self, by: &AssociatedKeys.viewModelUpdateObserver) else {
52+
let newObserver = PublishSubject<(ViewModelProtocol, DisposeBag)>()
53+
associate(self, withValue: newObserver, by: &AssociatedKeys.viewModelUpdateObserver)
54+
return newObserver
55+
}
56+
return existingObserver
57+
}
58+
}
59+
}
60+
61+
extension Reactive where Base: ViewModelHolderProtocol {
62+
public var viewModelDidUpdate: Observable<(Base.ViewModelProtocol, DisposeBag)> {
63+
return base._viewModelDidUpdate.asObservable()
64+
}
65+
}
66+
4667
fileprivate struct AssociatedKeys {
4768
static var disposeBag = "viewModel dispose bag associated key"
69+
static var viewModelUpdateObserver = "viewModel did update observer associated key"
4870
}

Diff for: Sources/NonReusableViewProtocol.swift

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ extension NonReusableViewProtocol where Self: AnyObject, Self.CompatibleType: An
3232
objc_sync_exit(self)
3333

3434
onUpdate(with: newVM, disposeBag: rx.disposeBag)
35+
_viewModelDidUpdate.onNext((newVM, rx.disposeBag))
3536
}
3637

3738
get {

Diff for: Sources/ReusableViewProtocol.swift

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ extension ReusableViewProtocol {
5555
guard let newVM = newValue else { return }
5656
objc_sync_exit(self)
5757
onUpdate(with: newVM, disposeBag: reuseBag)
58+
_viewModelDidUpdate.onNext((newVM, reuseBag))
5859
}
5960

6061
get {
@@ -80,6 +81,7 @@ extension ReusableViewProtocol where Self.ViewModelProtocol : Equatable {
8081
guard let newVM = newValue else { return }
8182
objc_sync_exit(self)
8283
onUpdate(with: newVM, disposeBag: reuseBag)
84+
_viewModelDidUpdate.onNext((newVM, reuseBag))
8385
}
8486

8587
get {

Diff for: Tests/NonReusableViewTests.swift

+11
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ class NonReusableViewTests: XCTestCase {
4545
XCTAssertTrue(object.errorReceivedViewModel == "321")
4646
}
4747

48+
func testViewModelObserver() {
49+
let object = TestNonReusable()
50+
let expect = expectation(description: "")
51+
_ = object.rx.viewModelDidUpdate.take(1).subscribe(onNext: {
52+
XCTAssert($0.0 == object.receivedViewModel)
53+
XCTAssert($0.0 == "a")
54+
expect.fulfill()
55+
})
56+
object.viewModel = "a"
57+
waitForExpectations(timeout: 1, handler: nil)
58+
}
4859
}
4960

5061
class TestNonReusable: NonReusableViewProtocol {

Diff for: Tests/ReusableViewTests.swift

+16-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import XCTest
1010
import RxSwift
11-
import RxCocoa
1211

1312
@testable import ReusableView
1413

@@ -139,6 +138,22 @@ class ReusableViewTests: XCTestCase {
139138
XCTAssertTrue(object.prepareForReuseCalled == 3)
140139
}
141140

141+
func testViewModelObserver() {
142+
let object : TestReusable = TestDistinctiveReusable()
143+
let expect = expectation(description: "")
144+
_ = object.rx.viewModelDidUpdate.take(1).subscribe(onNext: {
145+
XCTAssert($0.0 == object.receivedViewModel)
146+
XCTAssert($0.0 == "a")
147+
_ = object.rx.viewModelDidUpdate.take(1).subscribe(onNext: {
148+
XCTAssert($0.0 == object.receivedViewModel)
149+
XCTAssert($0.0 == "b")
150+
expect.fulfill()
151+
})
152+
object.viewModel = "b"
153+
})
154+
object.viewModel = "a"
155+
waitForExpectations(timeout: 1, handler: nil)
156+
}
142157
}
143158

144159

0 commit comments

Comments
 (0)