I'm building a wrapper for a textField that is used to introduce quantities. I'm trying to build everything with Combine. One of the use cases consists in that if the stringValue sent by the text field has a letter, I filter the letters and reassign the new value to the same var, so the text field filters these values. There's also a code to change this value to an int so other components can read the int value. Here's the code:
class QuantityPickerViewModel: ObservableObject {
private var subscriptions: Set<AnyCancellable> = Set<AnyCancellable>()
@Published var stringValue: String = ""
@Published var value : Int? = nil
init(initialValue: Int?) {
$stringValue
.removeDuplicates()
.print("pre-filter")
.map {
$0.filter {$0.isNumber}
}
.print("post-filter")
.map {
Int($0)
}
.assign(to: \.value, on: self)
.store(in: &subscriptions)
$value.map {
$0 != nil ? String($0!): ""
}
.print("Value")
.assign(to: \.stringValue, on:self)
.store(in: &subscriptions)
value = initialValue
}
}
I verify the behavior using tests, I'll just the test that fails:
class QuantityPickerViewModelTest: AppTestCase {
var model: QuantityPickerViewModel!
override func setUpWithError() throws {
super.setUp()
model = QuantityPickerViewModel(initialValue: 10)
}
func test_changeStringValueWithLetters_filtersLettersAndChangesValue() {
model.stringValue = "30a"
XCTAssertEqual(model.value, 30)
XCTAssertEqual(model.stringValue, "30") // fails saying stringValue is still "30a"
}
}
The output of the test is:
Test Case '-[SourdoughMasterTests.QuantityPickerViewModelTest test_changeStringValueWithLetters_filtersLettersAndChangesValue]' started.
pre-filter: receive subscription: (RemoveDuplicates)
post-filter: receive subscription: (Print)
post-filter: request unlimited
pre-filter: request unlimited
pre-filter: receive value: ()
post-filter: receive value: ()
Value: receive subscription: (PublishedSubject)
Value: request unlimited
Value: receive value: ()
Value: receive value: (10)
pre-filter: receive value: (10)
post-filter: receive value: (10)
Value: receive value: (10)
pre-filter: receive value: (30a)
post-filter: receive value: (30)
Value: receive value: (30)
pre-filter: receive value: (30)
post-filter: receive value: (30)
Value: receive value: (30)
/Users/jpellat/workspace/SourdoughMaster/SourdoughMasterTests/QuantityPickerViewModelTest.swift:54: error: -[SourdoughMasterTests.QuantityPickerViewModelTest test_changeStringValueWithLetters_filtersLettersAndChangesValue] : XCTAssertEqual failed: ("30a") is not equal to ("30")
Does anyone know why the value has not been assigned? Thanks