Here's the situation
I've a ViewModel (ok, follow the MVVM architecture), which has an array property, called "specialtySegments", and a flag property called "generic", I wanna when the generic value is changed, update the specialtySegments value again
Code snippet
- (instancetype)initWithTerritory:(SAPTerritory *)territory {
self = [super init];
if (self) {
_territory = territory;
_generic = NO;
_selectedProduct = [_products firstObject];
RAC(self, specialtySegments) = [self querySpecialtySegments];
}
return self;
}
- (RACSignal *)querySpecialtySegments {
return [[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[self asynQuerySpecialtySegments:^(NSArray *model) {
[subscriber sendNext:model];
[subscriber sendCompleted];
}];
return [RACDisposable disposableWithBlock:^{
}];
}] deliverOn:[RACScheduler mainThreadScheduler]] publish] autoconnect];
}
- (void)refreshData {
[self asynQuerySpecialtySegments:^(NSArray *model) {
dispatch_async(dispatch_get_main_queue(), ^{
self.specialtySegments = model;
});
}];
}
And in the ViewController
@weakify(self);
[[RACObserve(self.viewModel, specialtySegments) filter:^BOOL(id value) {
return (value != nil);
}] subscribeNext:^(id x) {
@strongify(self) {
[self.indicatorView stopAnimating];
self.indicatorView.hidden = YES;
[self.tableView reloadData];
}
}];
And some place to change the generic value, like
if (specialtyButton.selected == NO) {
self.viewModel.generic = NO;
genericButton.selected = NO;
specialtyButton.selected = YES;
[self.viewModel refreshData];
}
That's what I know to do now, it's not kind of fancy, I think.
Could I observe the generic property in the ViewModel, and subscripNext and first the signal again.
I've try like this, but code didn't enter the querySpecialtySegments, I put a breakpoint in the method.
[RACObserve(self, generic) subscribeNext:^(id x) {
[self querySpecialtySegments];
}];
and if I do like this, the asynQuerySpecialtySegments method would enter twice, as the RAC before, would run it once, I think
[RACObserve(self, generic) subscribeNext:^(id x) {
[self asynQuerySpecialtySegments:^(NSArray *model) {
dispatch_async(dispatch_get_main_queue(), ^{
self.specialtySegments = model;
});
}];
}];
I'm a newbie to ReactiveCocoa, trying using in the project, so is there a better way to the thing I described above, thanks guy
OK, after one day reading I think I've found the answer by myself
The key point is
Most signals start out "cold," which means that they will not do any work until subscription.
So this part code should change like this
[RACObserve(self, generic) subscribeNext:^(id x) {
[[self querySpecialtySegments] subscribeNext:^(id x) { // subscription is the key to trigger
self.specialtySegments = x; // would trigger the observer in view controller to do something
}];
}];
Updated: Personal idea is to observe generic property in ViewModel and then trigger View to update something is not a best option, some kind of black magic, without calling refresh or something, but the view refresh automatically. With a public method -reloadData is a good choice
- (void)refreshData {
@weakify(self);
[[self querySpecialtySegments] subscribeNext:^(id x) {
@strongify(self) {
self.specialtySegments = x;
}
}];
}