您的位置:首页 > Web前端 > React

MVVM Tutorial with ReactiveCocoa

2016-03-16 15:17 615 查看
Part One

*MVC separates the UI into the Model that represents the application state, the View, which in turn is composed of UI controls, and a Controller that handles user interactions and updates the model accordingly.

*At the core of MVVM is the ViewModel, which is a special type of model that represents the UI state of the application. It contains that detail the state of each and every UI control.

*Rules:

1. The View has a reference to the ViewModel, but not vice-versa.

2. The ViewModel has a reference to the Model, but not vice-versa.

Advantages:

1. Lightweight Views - All your UI logic resides within the ViewModel, resulting in a very lightweight view.

2. Testing - you should be able to run your entire application without the View, greatly enhancing its testability.

*

    RAC(self.viewModel, searchText) =self.searchTextField.rac_textSignal;
You're adding the rac_textSignal property to the UITextField class by using a category within ReactiveCocoa. It's a signal that emits a next event containing the current text each time the text field updates.

The RAC marco is a binding; the above code updates the searchText property of the viewModel with the contents of each next event emitted by the rac_textSignal.

*

    RACSignal *validSearchSignal = [[RACObserve(self, searchText)map:^id(NSString
*text) {

        return @(text.length >3);

    }] distinctUntilChanged];

    

    [validSearchSignal subscribeNext:^(id x) {

        NSLog(@"search text is valid %@", x);

    }];
The above code uses the RACObserve marco to create a signal from the ViewModel's searchText property (this is a ReactiveCocoa wrapper over KVO). Finally, distinctUntilChanges is used to ensure this signal only emits values when the state changes.

*RACCommand is 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.

*   

    self.searchButton.rac_command
= self.viewModel.executeSearch;

The rac_command property is a ReactiveCocoa addition to UIButton. The above code ensures that button taps result in the given command executing, and that the enabled state of the button reflects the enabled state of the command.

*

    RAC([UIApplicationsharedApplication],networkActivityIndicatorVisible)
= self.viewModel.executeSearch.executing;

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. You can use these to reflect the current command state elsewhere in your application.

*

 [self.viewModel.executeSearch.executionSignals subscribeNext:^(id
x) {

        [self.searchTextField resignFirstResponder];

    }];

The executionSignals property emits the signals that generate each time the command executes. This property is a signal of signals. Whenever a new command execution signal is created and emitted, the keyboard is hidden.

*The ViewModel exposes properties that represent the UI state, it also exposes commands - and often methods - that represent UI actions. It's responsible for managing changes to the UI state based on user interactions.
However, it's not responsible for the actual business logic that executes because of these interactions. That is the job of the Model.

*The Model layer exposes a 'service' that the ViewModel consumes:
1. The Model layer exposes services and is responsible for providing business logic for the application. In this case, it provides a service to search Flickr.
2. The ViewModel layer represents the view-state of the application. It also responds to user interactions and 'events' that come from the Model layer, each of which are reflected by changes in view-state.
3. The View layer is very thin and simply provides a visualization of the ViewModel state and forwards user interactions.

*rac_signalForSelector:fromProtocol: method creates the successSignal, and it also creates signals from delegate method invocations. Each time the delegate method is invoked, a next event emits with a RACTuple that contains the method arguments.

*Are you wondering why the implementation of the signalFromAPIMethod:arguments:transform: doesn't use these macros when referencing self?
It's because the block serves as an argument to the createSignal: method, which doesn't form a strong reference between self and the block.

Part Two
*The above adds a doNext operation to the signal the search command creates when it executes. The doNext block creates the new ViewModel that displays the search results, and then pushes it via the ViewModel-services.


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: