Search code examples
iosobjective-creactive-programmingreactive-cocoa

ReactiveCocoa - Stopping a command


I have a search text field which offers the user a list of autocomplete suggestions when he starts typing. The user can alternatively tap on a suggestion or press the search button of the keyboard to perform a search with the input text.

It could occur that if user starts typing and then presses search before waiting for the suggestions to appear, the suggestions table would be opened after the search has completed. As the suggestions result is triggered with a RACCommand, I need a way to stop such command when a search starts.

Here's how the search for suggestions is done:

@weakify(self);
[[[self.searchTextField.rac_textSignal.distinctUntilChanged ignore:@""] throttle:0.5] subscribeNext:^(id x) {
    @strongify(self);
    [self.suggestionsViewModel.rac_searchSuggestions execute:self.searchTextField.text];
}];

[self.suggestionsViewModel.rac_searchSuggestions.executionSignals.flatten
    subscribeNext:^(id x) {
        @strongify(self);
        [self.suggestionsTableView reloadData];
        [self viewDidLayoutSubviews]; // Update the suggestions table frame
}];

The search through the text field is triggered with:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [self.productsViewModel.rac_reloadCommand execute:textField.text];
    [textField resignFirstResponder];
    return YES;
}

How would you stop the suggestions look up and inhibit its table to be reloaded?

Based on Cancel RACCommand execution it seems that the solution would be the use of the takeUntil operator. Here's the rac_searchSuggestions, which should be the translation of "search for suggestions until a products search starts":

self.rac_searchSuggestions = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) {
    @strongify(self);
    return [[self rac_getProductsSuggestionsWithParameters:@{@"query":input}] 
            takeUntil:self.productsViewModel.rac_reloadCommand.executionSignal]];
}];

Unfortunately the takeUntil operator has no effect.

Many thanks, DAN


Solution

  • I think the problem is caused by throttle. It delayed the nexts from searchTextField.

    • If the next arrives before you hit the search button, everything is fine.
    • If it arrives after, the rac_getProductsSuggestionsWithParameters will be executed anyway.

    So you need to check the latter situation. E.g:

    if (self.searchTextField.isFirstResponder) {
        [self.suggestionsViewModel.rac_searchSuggestions execute:self.searchTextField.text]; 
    }