Reputation:
ItemDetailViewModel
is initialized with the following signature:
init(item: Item, didPressButton: Observable<Void>, api: FirebaseAPI)
It is initialized in ItemDetailViewController
, which gets an Item
from segue of source controller. Im realizing that ItemDetailViewController
is technically the View
, so it should not have Item
as a stored property. How else do I transfer Item
to ItemDetailViewModel
? This also means that ItemListViewController
shouldn't have a selectedItem
stored property to use in prepareFor(segue:)
.
Potential Solution
So when a CollectionView Cell
is tapped in ItemListViewController
(source controller), it should trigger ItemListViewModel
through binding to store Item
, and then perform segue
. Meanwhile, in prepareForSegue
I use ItemListViewModel
to initialize ItemDetailViewModel
with Item
. Ok.. That could work.
How do I handle the button taps, which changes its image on each tap? through a function?
What is the proper way to initialize view models
and inject dependencies
?
Upvotes: 2
Views: 1527
Reputation: 33967
You have an object that needs three pieces of data to be constructed, but one of the pieces of data comes from a different source than the other two. This is a good time to use higher-order functions.
struct ItemDetailViewModel {
static func factory(item: Item, api: FirebaseAPI) -> (_ action: Observable<Void>) -> ItemDetailViewModel {
return { action in
return ItemDetailViewModel(item: item, didPressButton: action, api: api)
}
}
}
Your view controller would accept the result of this function:
class ItemDetailViewController: UIViewController {
var viewModelFactory: (Observable<Void>) -> ItemDetailViewController = { _ in fatalError("factory called before provided.") }
override func viewDidLoad() {
super.viewDidLoad()
let viewModel = viewModelFactory(myButton.rx.tap.asObservable())
// bind output to view model
}
}
Then in your previous view controller's prepare for segue:
if let controller = segue.destinationViewController as? ItemDetailViewController {
controller.viewModelFactory = ItemDetailViewModel.factory(item: anItem, api: api)
}
Upvotes: 2