iOS 基于 MVVM 编程实践(附上简单的demo)

关于 MVVM 和 MVC 的详解 以及优缺点可以移步到参考链接,这里不再做多解释了。写这篇文章主要是想表达MVVM一个简单的实现(有很多大神也发了很多demo 过于复杂)。

MVVM 实践
1497882-3a8a210bb3fec848.png
MVVM_demo.png

上面是这个 demo 的文件结构
View文件:自定义的view
Model文件: 数据
ViewModel文件:业务逻辑,网络请求,数据缓存,UI状态,但不包括任何UIKit的类
ViewController文件:只负责 UI更新,UI跳转业务


1497882-96a45f40ccd593ce.png
MVVM.png

根据 MVVM 通讯思想


1497882-04a10168e7ea3b5f.png
屏幕快照 2019-01-14 下午4.52.27.png

所有的 业务逻辑,网络请求,数据缓存,UI的状态 都包括在 ViewModel 里面。

@interface JNViewModel : JNBaseViewModel

@property (nonatomic, assign) BOOL refreshBtnEnabled;/**<更新按钮是否可以点击 默认为Yes*/
@property (nonatomic, assign) BOOL refreshBtnHidden;/**<更新按钮是否显示 默认为NO*/
@property (nonatomic, assign) BOOL tableViewHidden;/**<列表是否展示 默认为YES*/
@property (nonatomic, strong) NSMutableArray *datas;/**<数据*/

//点击按钮加载数据
- (void)refreshBtnAction;

- (void)didSelectAction:(NSInteger)row;
@end

ViewModel.m 把 业务逻辑,网络请求,数据缓存 从 MVC 中的 Controller 拆分出来

//设置初始状态
- (instancetype)init{
    self = [super init];
    if (self) {
        _refreshBtnHidden = NO;
        _tableViewHidden = YES;
        _refreshBtnEnabled = YES;
        _datas = [NSMutableArray new];
    }
    return self;
}
//响应事件更新数据逻辑处理
- (void)refreshBtnAction {
    //请求数据前更新UI
    self.refreshBtnEnabled = NO;
    if ([self.updateUIDelegate respondsToSelector:@selector(updateUI)]){
        [self.updateUIDelegate updateUI];
    }
    
    //网络请求,数据缓存
    [[NSOperationQueue new] addOperationWithBlock:^{
        sleep(3);
        [self.datas removeAllObjects];
        for (int i = 0; i<30; i++) {
            JNModel *model = [[JNModel alloc] init];
            model.name = [NSString stringWithFormat:@"test%d",i];
            model.idNumber = [NSString stringWithFormat:@"atTest%d",i];
            [self.datas addObject:model];
        }

        //请求数据后更新UI
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.refreshBtnEnabled = YES;
            self.refreshBtnHidden = YES;
            self.tableViewHidden = NO;
            if ([self.updateUIDelegate respondsToSelector:@selector(updateUI)]){
                [self.updateUIDelegate updateUI];
            }
        }];
    }];
}

//cell点击数据业务处理
- (void)didSelectAction:(NSInteger)row {
    JNModel *model = self.datas[row];
    if ([self.updateUIDelegate respondsToSelector:@selector(didSelectAction:)]){
        [self.updateUIDelegate didSelectAction:model.name];
    }
}

在 ViewModel 的基类 BaseViewModel 设置 更新UI的代理 以及 点击事件触发是需要更新UI的代理

@protocol JNViewModelUpdateUIDelegate <NSObject>
//更新UI的代理
- (void)updateUI;
//响应代理
- (void)didSelectAction:(id)object;
@end


@interface JNBaseViewModel : NSObject
@property (nonatomic, weak) id <JNViewModelUpdateUIDelegate> updateUIDelegate;/**<更新UI的代理*/
@end

ViewController 只负责UI相关的逻辑

#pragma mark --JNViewModelUpdateUIDelegate
//更新ui
- (void)updateUI {
    self.tableView.hidden = self.viewModel.tableViewHidden;
    self.refreshBtn.hidden = self.viewModel.refreshBtnHidden;
    self.refreshBtn.enabled = self.viewModel.refreshBtnEnabled;
    
    if (!self.tableView.hidden) {
        [self.tableView reloadData];
    }
}
//ui业务处理
- (void)didSelectAction:(id)object {
    UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:object message:@"详细的说明" preferredStyle:UIAlertControllerStyleAlert];
    [alertVc addAction:[UIAlertAction actionWithTitle:@"关闭" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        
    }]];
    [self presentViewController:alertVc animated:YES completion:nil];
}
demo链接

https://github.com/Jniying/single_MVVM_Demo

参考链接

https://www.jianshu.com/p/caaa173071f3
https://www.jianshu.com/p/f1d0f7f01130
https://casatwy.com/iosying-yong-jia-gou-tan-wang-luo-ceng-she-ji-fang-an.html

(ps:有更好的建议和意见欢迎留言,共同学习进步)

猜你喜欢

转载自blog.csdn.net/weixin_34208185/article/details/87469016