|优化Smooth Scrolling in UITableView and UICollectionView|
- Avoid blocking the main thread while fetching data.
- Updating the table view right after we retrieve the data.
|move presentation logic out of the controller and into a new object, the view model.|
|is that it reduces the complexity of one’s view controllers and makes one’s presentation logic easier to test|
|On OS X, one can use Cocoa bindings, but we don’t have that luxury on iOS. Key-value observation comes to mind, and it does a great job. However, it’s a lot of boilerplate for simple bindings, especially if there are lots of properties to bind to. Instead, I like to use ReactiveCocoa, but there’s nothing forcing one to use ReactiveCocoa with MVVM. MVVM is a great paradigm that stands on its own and is only made better with a nice binding framework.|
Looking better! This diagram accurately describes what MVVM is: an augmented version of MVC where we formally connect the view and controller, and move presentation logic out of the controller and into a new object, the view model. MVVM sounds complicated, but it’s essentially a dressed-up version of the MVC architecture that you’re already familiar with.
If you’re interested in learning more about MVVM, you can check out this blog post explaining the benefits of MVVM in greater detail, or this article about how we used MVVM on a recent project of mine to great success. I also have a fully tested, MVVM-based app called C-41 that’s open sourced.
- Only the when loading the table view the first time, by placing it in viewDidLoad().
- Every time the table view is displayed, by placing it in viewWillAppear(_:).
- On user demand (for instance via a pull-down-to-refresh), by placing it in the method call that will take care of refreshing the data.
Since using a transparent layer or applying a gradient requires a good amount of computation, if possible, we should avoid using them to improve scrolling performance. In particular, we should avoid changing the alpha value and preferably use a standard RGB color (avoid UIColor.clear) for the cell and any image it contains:
Under MVVM, the view and view controller become formally connected; we treat them as one. Views still don’t have references to the model, but neither do controllers. Instead, they reference the view model.
View 和 view Controller 是连接到一起的。view 不应该引用model和controler，而是 引用view model
The view model is an excellent place to put validation logic for user input, presentation logic for the view, kick-offs of network requests, and other miscellaneous code. view model 适合放校验逻辑，view的展示逻辑，网络请求的开始，和其它代码
The logic in the view model should be just as applicable on iOS as it is on OS X. (In other words, don’t #import UIKit.h in your view models and you’ll be fine.)
The one thing that does not belong in the view model is any reference to the view itself.
不属于view model的，应该属于 view自身。
view mode 的逻辑应该是适当的（也就是说不要引入 UIKit.h之类的UI头文件）
Since presentation logic – like mapping a model value to a formatted string – belong in the view model, view controllers themselves become far, far less bloated. The best part is that when you’re starting off using MVVM, you can place only a little bit of logic in your view models, and migrate more of it over to them as you become more comfortable with the paradigm. 你可以只以小部分业务逻辑到 view model中，然后再不断的往view model中迁移更多的业务，当你更适应的时候。
iOS apps written using MVVM are highly testable; since the view model contains all the presentation logic and doesn’t reference the view, it can be fully tested programmatically. The numerous hacks involved in testing Core Data models notwithstanding, apps written using MVVM can be fully unit tested.
The results of using MVVM, in my experience, is a slight increase in the total amount of code, but an overall decrease in code complexity. A worthwhile tradeoff.
If you look again at the MVVM diagram, you’ll notice that I’ve used the ambiguous verbs “notify” and “update”, but haven’t specified how to do that. You could use KVO, like with MVC, but that can quickly become unmanageable. In practice, using ReactiveCocoa is a great way to glue all the moving pieces together.
For more information on how to use MVVM in conjunction with ReactiveCocoa, read Colin Wheeler’s excellent write-up or check out an open source app I wrote. You can also read my book on ReactiveCocoa and MVVM.
As such applications grow in size and scope and are modified, complex maintenance issues begin to arise. These issues include the tight coupling between the UI controls and the business logic, which increases the cost of making UI modifications, and the difficulty of unit testing such code.
The components are decoupled from each other, thus enabling:
- Components to be swapped
- Internal implementation to be changed without affecting the others
- Components to be worked on independently
- Isolated unit testing
In addition to understanding the responsibilities of the three components, it’s also important to understand how the components interact with each other.
At the highest level, the view “knows about” the view model, and the view model “knows about” the model, but the model is unaware of the view model, and the view model is unaware of the view.
View –>own–> view model, viewmode –>own–> model
The view model isolates the view from the model classes and allows the model to evolve independently of the view.
The view is responsible for defining the structure, layout, and appearance of what the user sees on the screen. Ideally, the view is defined purely with XAML, with a limited code-behind that does not contain business logic.
In a Windows Phone application, a view is typically a page in the application. In addition, a view could be a sub-component of a parent view, or a DataTemplate for an object in an ItemsControl.
A view can have its own view model, or it can inherit its parent’s view model. A view gets data from its view model through bindings, or invoking methods on the view model. At run time, the view changes when UI controls respond to view model properties raising change notification events.
There are several options for executing code on the view model in response to interactions on the view, such as a button click or item selection. If the control is a Command Source, the control’s Command property can be data-bound to an ICommand property on the view model. When the control’s command is invoked, the code in the view model will be executed. In addition to commands, behaviors can be attached to an object in the view and can listen for either a command to be invoked or event to be raised. In response, the behavior can then invoke an ICommand on the view model or a method on the view model.
The model in MVVM is an implementation of the application’s domain model that includes a data model along with business and validation logic. Examples of model objects include repositories, business objects, data transfer objects (DTOs), Plain Old CLR Objects (POCOs), and generated entity and proxy objects.
The view model acts as an intermediary (中间人)between the view and the model, and is responsible for handling the view logic（负责处理view 的逻辑）.
Typically, the view model interacts with the model by invoking methods in the model classes. The view model then provides data from the model in a form that the view can easily use.
The view model retrieves data from the model and then makes the data available to the view, and may reformat the data in some way that makes it simpler for the view to handle.
The view model also provides implementations of commands that a user of the application initiates in the view. For example, when a user clicks a button in the UI, that action can trigger a command in the view model.
The view model may also be responsible for defining logical state changes that affect some aspect of the display in the view, such as an indication that some operation is pending.
In order for the view model to participate in two-way data binding with the view, its properties must raise the PropertyChanged event.
View models satisfy this requirement by implementing the INotifyPropertyChanged interface and raising the PropertyChanged event when a property is changed. Listeners can respond appropriately to the property changes when they occur.
For collections, the view-friendly System.Collections.ObjectModel.ObservableCollection is provided. This collection implements collection changed notification, relieving the developer from having to implement the INotifyCollectionChanged interface on collections.
MVVM leverages the data-binding capabilities in Silverlight to manage the link between the view and view model, along with behaviors and event triggers. These capabilities limit the need to place business logic in the view’s code-behind.
There are many approaches to connecting a view model to a view, including direct relations and container-based approaches. However, all share the same aim, which is for the view to have a view model assigned to its DataContext property.
Views can be connected to view models in a code-behind file, or in the view itself.
A view can have code in the code-behind file that results in the view model being assigned as its DataContext property. This could be as simple as a view instantiating a new view model and assigning it to its DataContext, or injecting a view model into a view using an inversion-of-control container.
However, connecting a view model to a view in a code-behind file is discouraged as it can cause problems for designers in both Visual Studio and Microsoft Expression Blend® design software.
If a view model does not have any constructor arguments, the view model can be instantiated in the view as the view’s DataContext. A common approach to doing this is to use a view model locator. This is a resource which exposes the application’s view models as properties that individual views can data bind to. This approach means that the application has a single class that is responsible for connecting view models to views. In addition, it still leaves developers free to choose to manually perform the connection within the view model locator, or by using a dependency injection container.
MVVM enables a great developer-designer workflow, providing these benefits:
- During the development process, developers and designers can work more independently and concurrently on their components. The designers can concentrate on the view, and if they are using Expression Blend, they can easily generate sample data to work with, while the developers can work on the view model and model components.
- The developers can create unit tests for the view model and the model without using the view. The unit tests for the view model can exercise exactly the same functionality as used by the view.
- It is easy to redesign the UI of the application without touching the code because the view is implemented entirely in XAML. A new version of the view should work with the existing view model.
- If there is an existing implementation of the model that encapsulates existing business logic, it may be difficult or risky to change. In this scenario, the view model acts as an adapter for the model classes and enables you to avoid making any major changes to the model code.