ref: http://www.sprynthesis.com/2014/12/06/reactivecocoa-mvvm-introduction/

The MVVM relies on data-binding, a framework level feature that automatically connects object properties to UI controls. But iOS lacks a data-binding framework.

Controller:

Controller holds the viewModel with weak attribute.

RWTFlickrSearchViewController.h:

@interface RWTFlickrSearchViewController : UIViewController

- (instancetype)initWithViewModel:(RWTFlickrSearchViewModel *)viewModel;

@end

RWTFlickrSearchViewController.m:

@property (weak, nonatomic) RWTFlickrSearchViewModel *viewModel;

- (instancetype)initWithViewModel:(RWTFlickrSearchViewModel *)viewModel {
  self = [super init];
  if (self ) {
    _viewModel = viewModel;
  }
  return self;
}

- (void)viewDidLoad {
  // ...
  [self bindViewModel];
}

- (void)bindViewModel {  
  self.title = self.viewModel.title;

  // 每次textField的值发生变化, viewModel相对应的property都会相应的改变
  RAC(self.viewModel, searchText) = self.searchTextField.rac_textSignal;

  // button taps result in the given command executing
  // the "enabled" state of the button reflects the enabled state of the command.
  self.searchButton.rac_command = self.viewModel.executeSearch;

  // whenever the command executes, the small network activity indicator in the status bar will show itself.
  RAC([UIApplication sharedApplication], networkActivityIndicatorVisible) =
  self.viewModel.executeSearch.executing;

  //
  RAC(self.loadingIndicator, hidden) =
  [self.viewModel.executeSearch.executing not];


  [self.viewModel.executeSearch.executionSignals
    subscribeNext:^(id x) {
      [self.searchTextField resignFirstResponder];
    }];
}

RAC: binding self.viewModel.searchText with the content in the signal self.searchTextField.rac_textSignal;

RACCommand exposes an executing property, and that’s a signal that emits true and false events to indicate when the command starts and ends execution.

The executionSignals property emits the signals that generate each time the command executes.

ViewModel:

RWTFlickrSearchViewModel.h

@interface RWTFlickrSearchViewModel : NSObject

@property (strong, nonatomic) NSString *searchText;
@property (strong, nonatomic) NSString *title;

@property (strong, nonatomic) RACCommand *executeSearch;

@end

RACCommand: a ReactiveCocoa concept that represents a UI action. It comprises a signal, which is the result of the UI action, and the current state, which indicates whether the action is currently being executed.

RWTFlickrSearchViewModel.m

- (instancetype)init {
  self = [super init];
  if (self) {
    [self initialize];
  }
  return self;
}

- (void)initialize {
  self.title = @"Flickr Search";

  // 观测property
  RACSignal *validSearchSignal =
    [[RACObserve(self, searchText)
      map:^id(NSString *text) {
         return @(text.length > 3);
      }]
      distinctUntilChanged]; //  distinctUntilChanges is used to ensure this signal only emits values when the state changes.

  [validSearchSignal subscribeNext:^(id x) {
    NSLog(@"search text is valid %@", x);
  }];

  // 创建search command: 每当validSearchSignal emits true, 就return信号
  self.executeSearch =
  [[RACCommand alloc] initWithEnabled:validSearchSignal
    signalBlock:^RACSignal *(id input) {
      return [self executeSearchSignal];
    }];
}

- (RACSignal *)executeSearchSignal {
  return [[[[RACSignal empty]
           logAll]
           delay:2.0]
           logAll];
}

results matching ""

    No results matching ""