I have a VC(A) that has a container view and changes the VC(B-C) it based on the segementControl value, Im sending a request and getting a response inside the A ViewController and i want to make sure both B and C view controllers observe the response from A and set the data
Im new to rxswift so bear with me please
initiating both child VCS inside A VC
private lazy var profileVC: ProfileVC = {
// Load Storyboard
let storyboard = UIStoryboard(name: "Profile", bundle: Bundle.main)
// Instantiate View Controller
var viewController = storyboard.instantiateViewController(withIdentifier: "ProfileVC") as! ProfileVC
// Add View Controller as Child View Controller
self.add(asChildViewController: viewController)
return viewController
}()
private lazy var socialMediaVC: SocialMediaVCViewController = {
// Load Storyboard
let storyboard = UIStoryboard(name: "Profile", bundle: Bundle.main)
// Instantiate View Controller
var viewController = storyboard.instantiateViewController(withIdentifier: "SocialMediaVC") as! SocialMediaVCViewController
// Add View Controller as Child View Controller
self.add(asChildViewController: viewController)
return viewController
}()
adding and removing functions inside A ViewController
func add(asChildViewController viewController: UIViewController) {
// Add Child View as Subview
containerView.addSubview(viewController.view)
// Configure Child View
viewController.view.frame = view.bounds
viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
private func remove(asChildViewController viewController: UIViewController) {
// Notify Child View Controller
viewController.willMove(toParent: nil)
// Remove Child View From Superview
viewController.view.removeFromSuperview()
// Notify Child View Controller
viewController.removeFromParent()
}
segemntController change
@IBAction func segmentedControlClicked(_ sender: UISegmentedControl) {
segmentedControl.changeUnderlinePosition()
if segmentedControl.selectedSegmentIndex == 0 {
remove(asChildViewController: socialMediaVC)
add(asChildViewController: profileVC)
} else {
remove(asChildViewController: profileVC)
add(asChildViewController: socialMediaVC)
}
}
sending request and getting response inside A ViewModel:
startedUp.accept(true)
startedUp.filter({ $0})
.flatMap{ [weak self] _ -> Observable<Event<Result<ProfileResponse>>> in
self?.loadInProgress.accept(true)
return network.showProfile(startupId: 1).materialize()}
.subscribe(onNext: { [weak self] event in
self?.loadInProgress.accept(false)
switch event {
case .next(let result):
switch result{
case .Success(let response):
self?.startedUp.accept(false)
self?.sectionSubject.onNext(0)
self?.output.editProfileData = (self?.setProfileData(response:response))!
self?.tableViewcellsSubject.onNext((self?.createArray(response: response))!)
self?.userscellsSubject.onNext((self?.createUserArray(response: response.users!))!)
case .Failure(let error):
self?.errorsSubject.onNext(error)
}
case .error( _):
print("error")
default:
break
}
})
.disposed(by: disposeBag)
Let's say your AViewModel
has stream of data your children interested in:
protocol AViewModel {
let importantDataStream: Observable<SomeData> { get }
}
And your ParentVC
has reference on his view model as:
var viewModel: AViewModel
Then you could declare protocol:
protocol ImportantDataListener {
func subscribe(to stream: Observable<SomeData>)
}
And both B and C will conform to this protocol.
Then we change declaration of add(asChildViewController ...)
function like that:
func add(asChildViewController viewController: UIViewController & ImportantDataListener) {
// Add Child View as Subview
containerView.addSubview(viewController.view)
// Configure Child View
viewController.view.frame = view.bounds
viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// Passing stream
viewController.subscribe(to: viewModel.importantDataStream)
}