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.