Coder Social home page Coder Social logo

lovemo / mvvmframework Goto Github PK

View Code? Open in Web Editor NEW
1.7K 60.0 450.0 16.71 MB

(OC版)总结整理下一个快速开发框架,以更优雅的方式写代码,做一个代码艺术家。分离控制器中的代码,已加入cell自适应高度,自动缓存网络请求代码,降低代码耦合,提高开发效率。

License: MIT License

Objective-C 98.98% Ruby 0.09% Shell 0.73% C++ 0.03% C 0.17%

mvvmframework's Introduction

image

MVVMFramework

本项目交流群:474292335

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

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

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

博客:浅谈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学习文章

mvvmframework's People

Contributors

1074653827 avatar lovemo avatar randomprocess avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mvvmframework's Issues

小小的疑问

既然MVVM是解耦View和Model之间的关系的,就是独立View和Model ,这样如果要复用这个View的时候就很方便 ,比如我把这个View拖进另外一个工程,就能使用,但是你这个工程并没有独立View和model ,在View里面直接引入Model ,你觉得这个是真正意义上的MVVM?我要复用这个View 我还要有一个一样的Model,这不是耦合吗?

MVVM就是一种垃圾框架。

MVC的本质是模型,视图,控制器,其中的模型是指业务模型而不是数据模型。因此MVC本身就能解决现有的各种应用场景。何必要新使用一套MVVM框架,那你置C的地位何在。

你好 请问

这个SMKAction是你自己封装的 还是 第三方的呢?
[[SMKAction sharedAction] sendRequestBlock:^(NSObject *request) {

// // 方式2
// return [[FirstRequest alloc]init];

    // 方式3
    //smk_url (如果设置了url,则不需要在设置scheme,host,path 属性)
    request.smk_scheme = @"https";
    request.smk_host = @"api.douban.com";
    request.smk_path = @"/v2/book/search";
    request.smk_method = SMKRequestMethodGET;     // default
    request.smk_params = @{@"q": @"基础"};

    return request;

} progress:nil success:^(id responseObject) {
    if (responseObject) {
        NSArray *modelArray = [FirstModel mj_objectArrayWithKeyValuesArray:responseObject[@"books"]];
        success(modelArray);
    }
} failure:nil]

循环引用问题

ThirdVC.m的viewDidLoad方法里:

SMKMediator *mediator = [SMKMediator mediatorWithViewModel:self.viewModel viewManger:self.thirdViewManger];
self.thirdViewManger.smk_mediator = mediator;
self.viewModel.smk_mediator = mediator;

这段会有循环引用问题?

感觉更像mvp呢

大致看了下,让view和model耦合,感觉不好吧,view的复用呢,还有我感觉mvvm中要有双向绑定,不然和mvp有何区别呢

如果一个页面有多个网络请求, 一个ViewModel怎么区分

如果一个页面有多个网络请求, 一个ViewModel怎么区分

    [self.viewModel smk_viewModelWithProgress:nil success:^(id responseObject) {
        [self.tableViewModel getDataWithModelArray:^NSArray * _Nonnull{
            return responseObject;
        } completion:^{
            [self.tableView reloadData];
        }];
    } failure:^(NSError *error) {
        
    }];```

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.