(OC版)总结整理下一个快速开发框架,以更优雅的方式写代码,做一个代码艺术家。分离控制器中的代码,已加入cell自适应高度,自动缓存网络请求代码,降低代码耦合,提高开发效率。
Objective-C Other
Latest commit e53e47a Jun 16, 2016 @lovemo committed on GitHub add icon
Permalink
Failed to load latest commit information.
SUIMVVMDemo fix a bug May 2, 2016
SUIMVVMKit fix a bug May 2, 2016
resources add icon Jun 16, 2016
source Update README.md Mar 13, 2016
.DS_Store fix a typo Apr 18, 2016
.gitignore Update SUIUtils Mar 17, 2016
LICENSE Initial commit Dec 23, 2015
README.md add icon Jun 16, 2016
SUIMVVMKit.podspec 新增模型归档自动化 Apr 29, 2016

README.md

image

MVVMFramework

Swift版本地址:https://github.com/lovemo/MVVMFramework-Swift

本项目交流群:474292335

欢迎有兴趣的有好的想法的参与到项目中来

Tip:SMKStore是在YTKKeyValueStore的基础上直接增加了很多的相关功能函数,(偷懒😄)
感谢小学生提供的图标

具体实现思路,请参看博客:

博客:浅谈MVVM

地址:点击链接进入

获取更多MVVM推荐文章

总结整理下一个快速开发MVVM框架(抛砖引玉),主要用于分离控制器中的代码,降低代码耦合程度,可以根据自己使用习惯调整代码。欢迎来喷,提issues。代码加入了cell自适应高度,使用SMKStore缓存数据至sqlite数据库,更加高效的数据库存储库(Tip:存储自定义模型时,为了方便,数据库存储的为其转化为json后的数据,所以当读取时,请在自行转为模型即可,<利用MJExtension一行代码即可>)。

usage:

CocoaPods:

    pod 'SUIMVVMKit'
  • 详细用法,请参看demo

思维流程图示

image image

现在的工程代码结构

image

模块构建


结构分析


代码示例

部分protocol定义

@protocol SMKViewMangerProtocol <NSObject>

@optional

/**
 *  设置Controller的子视图的管理者为self
 *
 *  @param superView 一般指subView所在控制器的view
 */
- (void)smk_viewMangerWithSuperView:(UIView *)superView;

/**
 *  设置subView的管理者为self
 *
 *  @param subView 管理的subView
 */
- (void)smk_viewMangerWithSubView:(UIView *)subView;

/**
 *  设置添加subView的事件
 *
 *  @param view 管理的subView
 *  @param info 附带信息,用于区分调用
 */
- (void)smk_viewMangerWithHandleOfSubView:(UIView *)subView info:(NSString *)info;

/**
 *  返回viewManger所管理的视图
 *
 *  @return viewManger所管理的视图
 */
- (__kindof UIView *)smk_viewMangerOfSubView;

/**
 *  得到其它viewManger所管理的subView,用于自己内部
 *
 *  @param views 其它的subViews
 */
- (void)smk_viewMangerWithOtherSubViews:(NSDictionary *)viewInfos;

/**
 *  需要重新布局subView时,更改subView的frame或者约束
 *
 *  @param block 更新布局完成的block
 */
- (void)smk_viewMangerWithLayoutSubViews:(void (^)( ))updateBlock;

/**
 *  使子视图更新到最新的布局约束或者frame
 */
- (void)smk_viewMangerWithUpdateLayoutSubViews;

/**
 *  将model数据传递给viewManger
 */
- (void)smk_viewMangerWithModel:(NSDictionary * (^) ( ))dictBlock;

/**
 *  处理viewBlock事件
 */
- (ViewEventsBlock)smk_viewMangerWithViewEventBlockOfInfos:(NSDictionary *)infos;

/**
 *  处理ViewModelInfosBlock
 */
- (ViewModelInfosBlock)smk_viewMangerWithViewModelBlockOfInfos:(NSDictionary *)infos;

/**
 *  将viewManger中的信息通过代理传递给ViewModel
 *
 *  @param viewManger   viewManger自己
 *  @param infos 描述信息
 */
- (void)smk_viewManger:(id)viewManger withInfos:(NSDictionary *)infos;

@end

Controller中的代码

- (void)viewDidLoad {
    [super viewDidLoad];

       // 将thirdView的事件处理者代理给thirdViewManger (代理方式)
    [self.thirdView smk_viewWithViewManger:self.thirdViewManger];

    // self.thirdView.viewEventsBlock (block方式)
    self.thirdView.viewEventsBlock = [self.thirdViewManger smk_viewMangerWithViewEventBlockOfInfos:@{@"view" : self.thirdView}];

    // viewManger ----> info <-----  viewModel 之间通过代理方式交互
    self.thirdViewManger.viewMangerDelegate = self.viewModel;
    self.viewModel.viewModelDelegate = self.thirdViewManger;

    // viewManger ----> info <-----  viewModel 之间通过block方式交互
    self.thirdViewManger.viewMangerInfosBlock = [self.viewModel smk_viewModelWithViewMangerBlockOfInfos:@{@"info" : @"viewManger"}];

    // 中介者传值
    SMKMediator *mediator = [SMKMediator mediatorWithViewModel:self.viewModel viewManger:self.thirdViewManger];

    self.thirdViewManger.smk_mediator = mediator;
    self.viewModel.smk_mediator = mediator;

    self.thirdViewManger.smk_viewMangerInfos = @{@"xxxxxx" : @"22222222"};
    [self.thirdViewManger smk_notice];
    NSLog(@"viewManger------>viewModel==%@", self.viewModel.smk_viewModelInfos);

    self.viewModel.smk_viewModelInfos = @{@"oooooo" : @"888888888"};
    [self.viewModel smk_notice];
    NSLog(@"viewModel=====>viewManger==%@", self.thirdViewManger.smk_viewMangerInfos);
}

- (IBAction)clickBtnAction:(UIButton *)sender {

    // thirdView 通过viewModel传递的model来配置view
    [self.thirdView smk_configureViewWithViewModel:self.viewModel];

}

配置ViewModel

#pragma mark 加载网络请求
- (NSURLSessionTask *)smk_viewModelWithProgress:(progressBlock)progress success:(successBlock)success failure:(failureBlock)failure {
    return [[SMKAction sharedAction] sendRequestBlock:^id<SMKRequestProtocol>{
        return [[ThirdRequest alloc]init];
    } progress:nil success:^(id responseObject) {
        NSArray *modelArray = [ThirdModel mj_objectArrayWithKeyValuesArray:responseObject[@"books"]];
        if (success) {
            success(modelArray);
        }

    } failure:^(NSError *error) {

    }];
}

- (id)getRandomData:(NSArray *)array {
    u_int32_t index = arc4random_uniform((u_int32_t)10);
    return array[index];
}

#pragma mark 配置加工模型数据,并通过block传递给view
- (void)smk_viewModelWithModelBlcok:(void (^)(id))modelBlock {
    [self smk_viewModelWithProgress:nil success:^(id responseObject) {
        if (modelBlock) {

            if (self.viewModelDelegate && [self.viewModelDelegate respondsToSelector:@selector(smk_viewModel:withInfos:)]) {
                [self.viewModelDelegate smk_viewModel:self withInfos:@{@"info" : @"呵呵, 你好, 我是ViewModel,我加载数据成功了"}];
            }

            modelBlock([self getRandomData:responseObject]);
        }
    } failure:nil];

}

#pragma mark ViewManger delegate
- (void)smk_viewManger:(id)viewManger withInfos:(NSDictionary *)infos  {
    NSLog(@"%@",infos);
}

#pragma mark ViewManger Block
- (ViewMangerInfosBlock)smk_viewModelWithViewMangerBlockOfInfos:(NSDictionary *)infos {
    return ^{
      NSLog(@"hello");
    };
}

配置viewManger

#pragma mark UIView的delegate方法
- (void)smk_view:(__kindof UIView *)view withEvents:(NSDictionary *)events {

    NSLog(@"----------%@", events);
    if ([[events allKeys] containsObject:@"jump"]) {
        FirstVC *firstVC = [UIViewController sui_viewControllerWithStoryboard:nil identifier:@"FirstVCID"];
        [view.sui_currentVC.navigationController pushViewController:firstVC animated:YES];
    }

}

#pragma mark ViewEvents Block
- (ViewEventsBlock)smk_viewMangerWithViewEventBlockOfInfos:(NSDictionary *)infos {

    return ^(NSString *info){

        if (self.viewMangerInfosBlock) {
            self.viewMangerInfosBlock();
        }

        if (self.viewMangerDelegate && [self.viewMangerDelegate respondsToSelector:@selector(smk_viewManger:withInfos:)]) {
            [self.viewMangerDelegate smk_viewManger:self withInfos: @{@"info" : @"哈哈,你好ViewModel,我是viewManger,我被点击了"}];
        }

    //    NSLog(@"%@",info);
     //   [view smk_configureViewWithModel:self.dict[@"model"]];
    };
}

#pragma mark ViewModel delegate
- (void)smk_viewModel:(id)viewModel withInfos:(NSDictionary *)infos {
    NSLog(@"%@",infos);
}

配置Request模型

- (void)smk_requestConfigures {

    self.smk_scheme = @"https";
    self.smk_host = @"api.douban.com";
    self.smk_path = @"/v2/book/search";
    self.smk_method = SMKRequestMethodGET;

}

- (id)smk_requestParameters {
    return @{@"q": @"基础"};
}

SMKAction发送网络请求

- (NSURLSessionTask *)smk_viewModelWithProgress:(progressBlock)progress success:(successBlock)success failure:(failureBlock)failure {
    return [[SMKAction sharedAction] sendRequestBlock:^id<SMKRequestProtocol>{
        return [[FirstRequest alloc]init];
    } progress:nil success:^(id responseObject) {
        if (responseObject) {
            NSArray *modelArray = [FirstModel mj_objectArrayWithKeyValuesArray:responseObject[@"books"]];
            success(modelArray);
        }
    } failure:^(NSError *error) {

    }];

}

demo效果

  • 只需实现加载请求以及配置自定义cell和上述代码,就能轻松实现以下效果,最重要的是代码解耦。

image

期待

  • 如果在使用过程中遇到BUG,希望你能Issues我,谢谢(或者尝试下载最新的代码看看BUG修复没有)
  • 如果在使用过程中发现功能不够用,希望你能Issues我,我非常想为这个框架增加更多好用的功能,谢谢

推荐(欢迎补充)

应用架构文章

部分来自原创微信公众平台-移动开发前线

MVVM学习文章