iOS MVVM架构的介绍

iOS MVVM模式(Model-View-ViewModel): 
1. Model层是少不了的了,我们得有东西充当DTO(数据传输对象),当然,用字典也是可以的,编程么,要灵活一些。Model层是比较薄的一层,如果学过Java的小伙伴的话,对JavaBean应该不陌生吧。 
2. ViewModel层,就是View和Model层的粘合剂,他是一个放置用户输入验证逻辑,视图显示逻辑,发起网络请求和其他各种各样的代码的极好的地方。说白了,就是把原来ViewController层的业务逻辑和页面逻辑等剥离出来放到ViewModel层。 
3. View层,就是ViewController层,他的任务就是从ViewModel层获取数据,然后显示。项目MVVM的使用


MVVM实现的基本条件(限本博客): 
1. JSONModel 
2. ReactiveCocoa(响应式编程) 
3. AFNetworking 
4. AFNetworking-RACExtensions–>AFNetworking-RACExtensions 
5. JSONModel-RACExtension–>JSONModel-RACExtensions 
6. 此外需要在自己的mac上搭建虚拟服务器模拟网络请求 
7. CocoaPods的安装使用

废话不多说,看部分代码(代码较多)! 

基本结构

Model文件夹

#import "XCBaseModel.h"

#import "userinfoModel.h"


@interface TestModel : XCBaseModel


@property NSString* city;

@property userinfoModel *user_info;


@end

#import <JSONModel/JSONModel.h>


@interface userinfoModel : JSONModel


@property NSString* user_name;

@property NSNumber* user_code;


@end


NetWork文件夹

#import "XCAPIManager+test.h"

#import "XCAPIManager+Analysis.h"

#import "TestModel.h"


@implementation XCAPIManager (test)


- (RACSignal *)test

{

    //此处使用的mac自带的模拟服务器

    return [[[[[self rac_GET:@"http://localhost/a.json" parameters:@{}] map:^id(id value) {

        return [self analysisRequest:value];

    }] flattenMap:^RACStream *(id value) {

        if([value isKindOfClass:[NSError class]]){

            return [RACSignal return:value];

        }

        return [self rac_MappingForClass:[TestModel class] array:value[@"topic_infos"]];

    }] logError] replayLazily];

}


@end


View/ViewController文件夹

#import "ViewController.h"

#import "TestViewModel.h"

#import "XCTableviewCellTest.h"


@interface ViewController ()<UITableViewDelegate,UITableViewDataSource>


#pragma clang diagnostic push

#pragma clang diagnostic ignored "-Wobjc-property-synthesis"

@property (strong, nonatomic) IBOutlet TestViewModel *viewModel;

#pragma clang diagnostic pop


@property (nonatomic,strong)NSArray* models;

@property (weak, nonatomic) IBOutlet UITableView *tableview;


@end


@implementation ViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    

    @weakify(self)

    [self.viewModel.testCommand execute:nil];

    [RACObserve(self.viewModel, tests) subscribeNext:^(NSArray* x) {

        @strongify(self)

        self.models = x;

        [self.tableview reloadData];

    }];

    // Do any additional setup after loading the view, typically from a nib.

}



- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}


#pragma mark - delegate / datasource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

    return self.models.count;

}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    static NSString* cellId = @"cell";

    XCTableviewCellTest* cell = [tableView dequeueReusableCellWithIdentifier:cellId];

    

    [cell bindModel:self.models[indexPath.row]];

    return cell;

}



@end


ViewModel文件夹

#import "TestViewModel.h"

#import "XCAPIManager+test.h"


@interface TestViewModel ()


@property (nonatomic,strong,readwrite) RACCommand* testCommand;

@property (nonatomic,strong,readwrite) NSArray* tests;


@end


@implementation TestViewModel


- (instancetype)init {

    if (self = [super init]) {

        

    }

    return self;

}


- (RACCommand *)testCommand

{

    if (!_testCommand) {

        @weakify(self)

        _testCommand = [[RACCommand alloc]initWithSignalBlock:^RACSignal *(id input) {

            @strongify(self)

            return [self.apiManager test];

        }];

        

        [[_testCommand.executionSignals concat] subscribeNext:^(NSArray* x) {

            @strongify(self)

            self.tests = x;

            NSLog(@"%@",x);

        }];

//        XPViewModelShortHand(_testCommand)

    }

    return _testCommand;

}


@end