美文网首页
OC ViewModel实践 2023-04-27 周四

OC ViewModel实践 2023-04-27 周四

作者: 勇往直前888 | 来源:发表于2023-04-26 19:09 被阅读0次

简介

OC 中MVC和MVVM的争论是一个经久不衰的话题。
MVC是入门;第一次接触MVVM,就非常认同其理念;再后来RAC也学习过,实践过,体验过双向绑定的神奇之处;再后来,小型项目又回归MVC;感觉MVVM像是双刃剑,跟MVC之间大约五五开的样子。

当前的选择

  • 整个工程师MVC的;因为RAC对于OC的支持在下降,其重心已经转向Swift;

  • 在某些地方,ViewModel还是能够带来便利的,比如表格;本次实践就是这个;

表格实践

界面截图

普通5_5.PNG

图片展示部分是横向表格,使用UICollectionView是最方便的

文件夹截图

企业微信截图_669d652b-07fd-4200-9054-31cc388ebe2a.png

这里的ViewModel是为cell服务的

基类ViewModel

  • 和Model类似,提供一个基类,进行一级继承,能够带来方便;

  • 和Model类似,利用YYModel实现<NSCopying, NSCoding>能带来很大的便利;

@interface WGBBaseViewModel : NSObject <NSCopying, NSCoding>

@end
#import "WGBBaseViewModel.h"
#import <YYModel/YYModel.h>

@implementation WGBBaseViewModel

#pragma mark - NSCopying, NSCoding

- (void)encodeWithCoder:(NSCoder *)coder {
    [self yy_modelEncodeWithCoder:coder];
}

- (instancetype)initWithCoder:(NSCoder *)coder {
    if (self = [super init]) {
        [self yy_modelInitWithCoder:coder];
    }
    return self;
}

- (id)copyWithZone:(NSZone *)zone {
    return [self yy_modelCopy];
}

- (NSUInteger)hash {
    return [self yy_modelHash];
}

- (BOOL)isEqual:(id)object {
    return [self yy_modelIsEqual:object];
}

@end

ViewModel的内容

  • 界面显示的内容,这些以属性的方式存在。
@interface WGBNormalCellViewModel : WGBBaseViewModel

#pragma mark - 属性

/// 图片的url
@property (copy, nonatomic, nullable) NSString *urlString;

/// 照片数据(原图数据)
@property (strong, nonatomic, nullable) UIImage *image;

/// 是否是远程图片
@property (assign, nonatomic) BOOL isRemote;

/// 添加图片结点,显示➕图怕
@property (assign, nonatomic) BOOL isAddNode;

@end

这个案例比较简单,主要区分远程图片(urlString),本地图片(image),以及排在最后的添加图片(isAddNode)

  • 构造方法,从数据创建。这个一般以构造方法存在。
@interface WGBNormalCellViewModel : WGBBaseViewModel

#pragma mark - 构造方法
/// 创建远程url结点
- (instancetype)initWithUrlString:(NSString *)urlString;

/// 创建本地图片结点
- (instancetype)initWithImage:(UIImage *)image;

/// 创建本地图片结点
- (instancetype)initAddNode;

@end

非常简单,就是提供三种不同结点的构造方法

Cell的定义

  • 只需要提供一个通过ViewModel更新界面的方法就可以了
@interface WGBNormalCell.h : UICollectionViewCell

/// 更新界面
- (void)updateWithViewModel:(WGBNormalCellViewModel *)viewModel;

@end
  • 界面元素,具体界面设置的方式,隐藏在.m文件中就可以了
#import "WGBNormalCell.h"

@interface WGBNormalCell ()

/// 主图片
@property (weak, nonatomic) IBOutlet UIImageView *mainImageView;

/// 类型图片
@property (weak, nonatomic) IBOutlet UIImageView *typeImageView;


@end

@implementation WGBNormalCell

/// 更新界面
- (void)updateWithViewModel:(WGBNormalCellViewModel *)viewModel {
    if (viewModel.isAddNode) {
        self.mainImageView.image = [UIImage imageNamed:@"添加图片"];
        self.typeImageView.hidden = YES;
        return;
    }
    
    self.typeImageView.hidden = NO;
    if (viewModel.isRemote) {
        self.typeImageView.image = [UIImage imageNamed:@"云端图片标志"];
        [self.mainImageView yy_setImageWithURL:[NSURL URLWithString:viewModel.urlString] options:YYWebImageOptionProgressive];
    } else {
        self.typeImageView.image = [UIImage imageNamed:@"相机图片标志"];
        self.mainImageView.image = viewModel.waterImage;
    }
}

@end

使用

  • 字典转模型,从网络接收数据
/// 字典转Model
WGBNormalPhotoModel *model = [WGBNormalPhotoModel instanceWithJSON:response targetClass:[WGBNormalPhotoModel class]];
  • 根据Model数据,调用构造方法,创建ViewModel
    NSMutableArray<WGBNormalCellViewModel *> *tempArray = [NSMutableArray arrayWithArray:self.nodeArray];
    
    /// 网络结点
    if ([WGBArrayUtil isNotEmpty:urlArray]) {
        for (NSString *urlString in urlArray) {
            WGBNormalCellViewModel *viewModel = [[WGBNormalCellViewModel alloc] initWithUrlString:urlString itemNo:self.itemNo];
            [tempArray addObject:viewModel];
        }
    }
    
    /// 照片结点
    if ([WGBArrayUtil isNotEmpty:imageArray]) {
        for (UIImage *image in imageArray) {
            WGBNormalCellViewModel *viewModel = [[WGBNormalCellViewModel alloc] initWithImage:image itemNo:self.itemNo];
            [tempArray addObject:viewModel];
        }
    }
    
    /// 结点数据源
    self.dataSource = [tempArray copy];
    
    /// 更新表格
    [self.imageCollectionView reloadData];
  • 在表格中动态创建Cell,更新界面
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    WGBNormalCell *cell =  [collectionView dequeueReusableCellWithReuseIdentifier:@"WGBNormalCell" forIndexPath:indexPath];
    WGBNormalCellViewModel *viewModel = self.dataSource[indexPath.row];
    [cell updateWithViewModel:viewModel];

    return cell;
}

小结

  • MVVM模式用在表格页面,能够使结构清晰,值得多套一层;

  • 如果是代码写View,增加一层ViewModel也是好的。表格跟代码写View情况类似。

  • 用故事版,还是直接在ViewController中写业务比较方便,加一层ViewModel反而更繁琐,不如直接用MVC来得简洁

  • 如果用RAC,用MVVM架构也是很不错的。反过来也一样,如果用MVVM架构,最好引入RAC这个黑科技

相关文章

网友评论

      本文标题:OC ViewModel实践 2023-04-27 周四

      本文链接:https://www.haomeiwen.com/subject/pfuvjdtx.html