MVC设计模式
MVC的核心是非常简单又非常好的设计理念
MVC有3部分组成
1. Model-数据模型
2. View-用户交互界面
3. Controller-控制器存在于Model和View之间
MVVM 一个更好的世界
MVVM的模型标准是 Model-View-ViewModel
MVVM与MVC的不同
在MVVM模式中View Model分装数据与属性,view可以绑定他,他可以展示任何的逻辑与动作。
例如:你需要修改一个按钮的title为你在View Model中申明的一个属性,你可以将View Model的属性绑定到按钮上。
我们不必关心UI测试
在标准控件上我们不必关心UI测试,我们只是在上边绑定View Model。
我们可以容易的修改UI
因为UI是绑定到视图模型,这意味着你应该能够交换组件仅仅是通过将属性绑定到视图模型和UI应该与以前一样工作。这也应该使UI设计人员更容易尝试着不同的view在你的应用程序中
ViewModel到底是什么?
看一个简单的使用ViewModel的例子
ViewModel实例
#import
@interface CDWPlayerViewModel : NSObject
@property(nonatomic, retain) NSString *playerName;
@property(nonatomic, assign) double points;
@property(nonatomic, assign) double stepAmount;
@property(nonatomic, assign) double maxPoints;
@property(nonatomic, assign) double minPoints;
@property(nonatomic, readonly) NSUInteger maxPointUpdates;
-(IBAction)resetToDefaults:(id)sender;
-(IBAction)uploadData:(id)sender;
-(RACSignal *)forbiddenNameSignal;
-(RACSignal *)modelIsValidSignal;
@end
ViewController
//
//ViewController.m
//racTestTwo
//
//Created by HEcom on 16/9/20.
//Copyright © 2016年Jorgon. All rights reserved.
//
#import"ViewController.h"
#import
#import"PlayerViewModle.h"
#import
@interfaceViewController()
@property(weak,nonatomic)IBOutletUITextField*iPlayerName;
@property(weak,nonatomic)IBOutletUIStepper*iStepper;
@property(nonatomic,strong)PlayerViewModle*iViewModel;
@property(weak,nonatomic)IBOutletUIButton*iUploadButton;
@property(weak,nonatomic)IBOutletUILabel*iScoreField;
@property(weak,nonatomic)IBOutletUILabel*iStepperValue;
@property(nonatomic,assign)NSUIntegerscoreUpdates;
@end
staticNSIntegerconstkMaxUploads =5;
@implementationViewController
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.iViewModel= [[PlayerViewModlealloc]init];
@weakify(self);
//Start binding our properties
RAC(self.iPlayerName,text) = [RACObserve(self.iViewModel, playerName)distinctUntilChanged];
[[self.iPlayerName.rac_textSignaldistinctUntilChanged]subscribeNext:^(idx) {
//this creates a reference to self that when used with @weakify(self);
//makes sure self isn't retained
@strongify(self);
self.iViewModel.playerName= x;
}];
//the score property is a double, RC gives us updates as NSNumber which we just call
//stringValue on and bind that to the scorefield text
RAC(self.iScoreField,text) = [RACObserve(self.iViewModel,points)map:^id(NSNumber*value) {
return[valuestringValue];
}];
//Setup bind the steppers values
self.iViewModel.points=self.iStepper.value;
RAC(self.iStepper,stepValue) =RACObserve(self.iViewModel,stepAmount);
RAC(self.iStepper,maximumValue) =RACObserve(self.iViewModel,maxPoints);
RAC(self.iStepper,minimumValue) =RACObserve(self.iViewModel,minPoints);
//bind the hidden field to a signal keeping track if
//we've updated less than a certain number times as the view model specifies
RAC(self.iStepper,hidden) = [RACObserve(self,scoreUpdates)map:^id(NSNumber*x) {
@strongify(self);
return@(x.intValue>=self.iViewModel.maxPointUpdates);
}];
//this signal should only trigger if we have "bad words" in our name
[self.iViewModel.forbiddenNameSignalsubscribeNext:^(NSString*name) {
@strongify(self);
UIAlertView*alert = [[UIAlertViewalloc]initWithTitle:@"Forbidden Name!"
message:[NSStringstringWithFormat:@"The name %@ has been forbidden!",name]
delegate:nil
cancelButtonTitle:@"Ok"
otherButtonTitles:nil];
[alertshow];
self.iViewModel.playerName=@"";
}];
//let the upload(save) button only be enabled when the view model says its valid
RAC(self.iUploadButton,enabled) =self.iViewModel.modelIsValidSignal;
//set the control action for our button to be the ViewModels action method
[self.iUploadButtonaddTarget:self.iViewModel
action:@selector(uploadData:)
forControlEvents:UIControlEventTouchUpInside];
//we can subscribe to the same thing in multiple locations
//here we skip the first 4 signals and take only 1 update
//and then disable/hide certain UI elements as our app
//only allows 5 updates
[[[[self.iUploadButton rac_signalForControlEvents:UIControlEventTouchUpInside]
skip:(kMaxUploads -1)] take:1] subscribeNext:^(idx) {
@strongify(self);
self.iPlayerName.enabled =NO;
self.iStepper.hidden =YES;
self.iUploadButton.hidden =YES;
}];
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
参考文档:http://cocoasamurai.blogspot.jp/2013/03/basic-mvvm-with-reactivecocoa.html