introduce

The MVVM mode renames Presenter to ViewModel, almost exactly the same as the MVP mode.

The only difference is that it uses two-way data-binding: View<->ViewModel, ViewModel as the mapping of the value of the Model, is when the data changes, notify the change in the View, do not need to consider the interaction between the View and Model update, just to start the interface layout logic.

  1. View and Model are not directly related, but through the ViewModel as a hub, communication between View and Model.
  2. The value of the control in the View is bound to the ViewModel property, observed by the KVO key value (so that the View automatically changes when the model value changes)

The View and Model are dynamically associated through the ViewModel.

code

Model

//.h
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Model : NSObject
@property(nonatomic,copy)NSString *name;

@end

NS_ASSUME_NONNULL_END

//.m
#import "Model.h"

@implementation Model

@end
Copy the code

ViewModel

//.h
#import <Foundation/Foundation.h>
#import "Model.h"

NS_ASSUME_NONNULL_BEGIN

@interface ViewModel : NSObject
@property(nonatomic,copy)NSString *nameStr;
@property(nonatomic,strong)Model *model;

-(void)setWithModel:(Model *)model;
-(void)clickChangeName;

@end

NS_ASSUME_NONNULL_END

//.m
#import "ViewModel.h"

@implementation ViewModel
-(instancetype)init{
    if (self = [super init]) {
    }
    return self;
}

-(void)setWithModel:(Model *)model{
    self.model = model;
    self.nameStr = model.name;
}

-(void)clickChangeName{
    self.model.name = [NSString stringWithFormat:@"name%d",arc4random()%10];
    self.nameStr = self.model.name;
    NSLog(@"% @",self.nameStr);
}
@end
Copy the code

View

//.h
#import <UIKit/UIKit.h>
#import "ViewModel.h"
NS_ASSUME_NONNULL_BEGIN

@interface View : UIView
-(void)setWithViewModel:(ViewModel *)vm;
@end

NS_ASSUME_NONNULL_END

//.m
#import "View.h"

@interface View ()
@property(nonatomic,strong)ViewModel *vm;
@property(nonatomic,strong)UILabel *label;
@property(nonatomic,strong)UIButton *button;

@end
@implementation View

- (instancetype)init {
    self = [super init];
    if(self) { self.backgroundColor = [UIColor whiteColor]; self.frame = [UIScreen mainScreen].bounds; Self. label = [[UILabel alloc]initWithFrame:CGRectMake(150,100,100, 30)]; self.label.backgroundColor = [UIColor orangeColor]; [self addSubview:_label]; self.button = [UIButton new]; _button.backgroundColor = [UIColor redColor]; [_buttonsetTitle:@"Click" forState:UIControlStateNormal];
        [_button addTarget:self action:@selector(mvvmClickChangModel) forControlEvents:UIControlEventTouchUpInside];
        _button.frame = CGRectMake(150, 200, 50, 50);
        [self addSubview:_button];
    }
    return self;
}

- (void)setWithViewModel:(ViewModel *)vm {
    self.vm = vm;
    //KVO
    [self.vm addObserver:self forKeyPath:@"nameStr" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
    self.label.text = vm.nameStr;
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:    (NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    if ([keyPath isEqualToString:@"nameStr"]&&[change objectForKey:NSKeyValueChangeNewKey]) {
        NSNumber *new = [change objectForKey:NSKeyValueChangeNewKey];
        self.label.text = [NSString stringWithFormat:@"% @",new];
    }
}

-(void)mvvmClickChangModel{
    [self.vm clickChangeName];
}

-(void)dealloc{
    [self.vm removeObserver:self forKeyPath:@"nameStr"];
}

@end
Copy the code

ViewController

//.m
#import "ViewController.h"
#import "View.h"
#import "Model.h"
#import "ViewModel.h"

@interface ViewController ()
@property (nonatomic, strong) ViewModel * viewModel;
@property (nonatomic, strong) View *pView;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    self.pView = [View new];
    Model *model = [Model new];
    model.name = @"name1"; ViewModel *viewModel = [ViewModel new]; [self.view addSubview:self.pView]; //*viewModel is used as a hub to communicate the relationship between view and modelsetWithModel:model];
    [self.pView setWithViewModel:viewModel];
}

@end
Copy the code

Reference MVVM