Reputation: 2303
I have the following code in my VC:
[RACObserve(self.viewModel, searchMode) subscribeNext:^(NSNumber *value) {
@strongify(self);
BOOL isSearchMode = [value boolValue];
self.searchBarView.hidden = !isSearchMode;
if (isSearchMode) {
[self.searchBar becomeFirstResponder];
self.yContentOffset = self.collectionView.contentOffset.y;
[self.collectionView setContentOffset:CGPointMake(self.collectionView.contentOffset.x, 0) animated:NO];
} else {
[self.searchBar resignFirstResponder];
[self.collectionView setContentOffset:CGPointMake(self.collectionView.contentOffset.x, self.yContentOffset) animated:NO];
}
}];
where yContentOffset
is VC's property which I am trying to remove. (It saves content offset before entering search mode and restores it after).
I've tried [RACSignal if: then: else:]
but did not managed to get it completely.
Upvotes: 2
Views: 2088
Reputation: 64022
You've got three distinct values that need to change when self.viewModel.searchMode
does, so I think the first thing you want to do is split the signal and take each of them separately.
RACSignal * searchModeSig = [[RACObserve(self.viewModel, searchMode) distinctUntilChanged]
publish]
signal];
The hidden
status is simple:
RAC(self.searchBarView, hidden) = [searchModeSig not];
I used distinctUntilChanged
above because your signal to the collection view's y offset seems to be "0 if the searchMode
is YES
, else the last non-zero value". If the searchMode
signal's value were to be YES
or NO
in succession, you'd also end up with a duplication in the stream of offset values, which would screw up using replayLast
to get the value you want. distinctUntilChanged
only passes along values that represent a transition from YES
to NO
or vice-versa.
RAC(self.collectionView, contentOffset) =
[RACSignal if:searchModeSig
then:[RACSignal return:[NSValue valueWithCGPoint:CGPointMake(self.collectionView.contentOffset.x, 0)]
else:[RACObserve(self.collectionView, contentOffset) replayLast]];
This should insert the 0 y
value into the stream whenever searchMode
transitions to YES
, and take the previous value (which, of course, could have been updated from elsewhere) whenever it transitions to NO
.
For the first responder status of the search bar, it seems reasonable to do that with subscribeNext:
, but you could also do this:
RAC(self.searchBar, DLShouldBeFirstResponder) = searchModeSig;
Where you've turned the becomeFirstResponder
and resignFirstResponder
calls into a pseudo-property like so:
@interface UIView (DLFirstResponderProp)
@property (assign, nonatomic) BOOL DLShouldBeFirstResponder;
@end
@implementation UIView (DLFirstResponderProp)
- (void)setDLShouldBeFirstResponder:(BOOL)shouldBe
{
if( shouldBe ){
[self becomeFirstResponder];
}
else {
[self resignFirstResponder];
}
}
- (BOOL)DLShouldBeFirstResponder
{
return [self isFirstResponder];
}
@end
It might also be that lifting would be the "official" way to go from signal to imperative call, but I'm not sure how/if that works with parameterless methods.
Upvotes: 3