ios mvvm框架的封装_iOS的MVVM框架

前言:iOS的MVVM如何工作呢?各自的职责是什么呢?首先我们先来介绍一下纯粹的MVVM架构模式,再来介绍MVVM的双向绑定。

来看一下MVVM的工作原理图:

mvvm.png

MVVM的通讯关系:

1.View与Model是不直接通讯的。

2.ViewController与Model是不直接通讯的。

3.View只与ViewController/View Model两者发生关系。

4.Model只与View Model通讯。

责任划分:

Model:业务逻辑处理、数据控制(本地数据、网络加载数据)。

View:显示用户可见得视图控件、与用户交互事件。

ViewModel:是组织生成和维护的视图数据层。在这一层开发者对从后端获取的 Model 数据进行转换处理,做二次封装,以生成符合 View 层使用预期的视图数据模型。

ViewController:界面的生命周期控制和业务间切换控制。

工程目录结构:

mvvm.png

MVVM代码实例:

Model:

//-----------MAnimalsModel----------

#import "MAnimalModel.h"

@protocol MAnimalModelDelegate;

@interface MAnimalsModel : NSObject

@property (nonatomic,weak) id delegate;

@property (nonatomic,strong) NSArray *dataSource;

- (void)downloadImageWtihModel:(MAnimalModel *)animalModel;

@end

@protocol MAnimalModelDelegate

- (void)animalShowImage:(MAnimalModel *)animalModel row:(NSInteger)row;

@end

#import "MAnimalsModel.h"

@implementation MAnimalsModel

- (instancetype)init {

self = [super init];

if (self) {

[self loadDataSource];

}

return self;

}

- (void)dealloc {

NSLog(@"%s",__func__);

}

- (NSArray *)loadJson {

NSString *path = [[NSBundle mainBundle] pathForResource:@"jsonString" ofType:@"json"];

NSData *jsonData = [NSData dataWithContentsOfFile:path];

NSError *error = nil;

id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:(NSJSONReadingMutableLeaves) error:&error];

if ([jsonObject isKindOfClass:[NSArray class]]) {

return jsonObject;

}

else {

return nil;

}

}

- (void)loadDataSource {

NSArray *array = [self loadJson];

NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:array.count];

for (NSDictionary *dictionary in array) {

MAnimalModel *model = [[MAnimalModel alloc] init];

model.identifier = [[NSDate date] timeIntervalSince1970];

model.imageUrl = [dictionary objectForKey:@"url"];

model.name = [dictionary objectForKey:@"name"];

model.summary = [dictionary objectForKey:@"summary"];

[mutableArray addObject:model];

}

_dataSource = mutableArray;

}

- (void)downloadImageWtihModel:(MAnimalModel *)animalModel {

if (animalModel.isLoading || !animalModel.imageUrl || animalModel.imageUrl.length == 0) {

return;

}

animalModel.isLoading = YES;

dispatch_async(dispatch_get_global_queue(0, 0), ^{

NSURL *imageURL = [NSURL URLWithString:animalModel.imageUrl];

NSData *imageData = [NSData dataWithContentsOfURL:imageURL];

if (imageData) {

animalModel.imageData = imageData;

}

NSLog(@"imageData = %@",imageData);

dispatch_async(dispatch_get_main_queue(), ^{

if (self.delegate && [self.delegate respondsToSelector:@selector(animalShowImage:row:)]) {

NSInteger row = [self.dataSource indexOfObject:animalModel];

[self.delegate animalShowImage:animalModel row:row];

}

});

});

}

@end

//---------MAnimalModel----------

@interface MAnimalModel : NSObject

@property (nonatomic,assign) NSInteger identifier;

@property (nonatomic,strong) NSData *imageData;

@property (nonatomic,copy) NSString *imageUrl;

@property (nonatomic,copy) NSString *name;

@property (nonatomic,copy) NSString *summary;

@property (nonatomic,assign) BOOL isLoading;

@end

#import "MAnimalModel.h"

@implementation MAnimalModel

- (void)dealloc {

NSLog(@"%s",__func__);

}

@end

View:

//---------------TableView-------------

#import "MAnimalsViewModel.h"

@interface MAnimalTableView : UITableView

@property (nonatomic,strong) MAnimalsViewModel *viewModel;

- (void)refreshData;

@end

#import "MAnimalTableView.h"

#import "MAnimalCell.h"

@interface MAnimalTableView()

@end

@implementation MAnimalTableView

- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style {

self = [super initWithFrame:frame style:style];

if (self) {

self.delegate = self;

self.dataSource = self;

self.viewModel = [[MAnimalsViewModel alloc] init];

self.viewModel.delegate = self;

}

return self;

}

- (void)dealloc {

NSLog(@"%s",__func__);

}

- (void)refreshData {

[self.viewModel reloadData];

}

#pragma mark -

#pragma mark -- MAnimalViewModel Delegate

- (void)viewModel:(MAnimalsViewModel *)viewModel reloadRow:(NSInteger)row {

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:0];

[self reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];

}

- (void)reloadDataWithViewModel:(MAnimalsViewModel *)viewModel {

[self reloadData];

}

#pragma mark -

#pragma mark -- Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

return 1;

}

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

return self.viewModel.dataSource.count;

}

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

static NSString *reuseIdentifier = @"reuseIdentifier";

MAnimalCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];

if (!cell) {

cell = [[MAnimalCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];

}

MAnimalViewModel *viewModel = [_viewModel animalEntityWitIndexPath:indexPath.row];

cell.textLabel.text = viewModel.name;

cell.detailTextLabel.text = viewModel.summary;

[cell showImageWithData:viewModel.imageData];

return cell;

}

#pragma mark -

#pragma mark -- UITableView Delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

[tableView deselectRowAtIndexPath:indexPath animated:YES];

}

- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath

{

UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive

title:@"Delete"

handler:^(UITableViewRowAction *action,

NSIndexPath *indexPath) {

[self.viewModel deleteWithRow:indexPath.row];

[tableView beginUpdates];

[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

[tableView endUpdates];

}];

return @[deleteAction];

}

@end

//-------------Cell--------------

@interface MAnimalCell : UITableViewCell

- (void)showImageWithData:(NSData *)data;

@end

#import "MAnimalCell.h"

@implementation MAnimalCell

- (void)awakeFromNib {

[super awakeFromNib];

// Initialization code

}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {

[super setSelected:selected animated:animated];

// Configure the view for the selected state

}

- (void)showImageWithData:(NSData *)data {

if (data) {

self.imageView.image = [UIImage imageWithData:data];

}

}

@end

ViewModel:

//-------------ViewModels--------------

#import "MAnimalViewModel.h"

@protocol MAnimalViewModelDelegate;

@interface MAnimalsViewModel : NSObject

@property (nonatomic,weak) id delegate;

@property (nonatomic,strong,readonly) NSMutableArray *dataSource;

- (MAnimalViewModel *)animalEntityWitIndexPath:(NSInteger)row;

- (void)deleteWithRow:(NSInteger)row;

- (void)reloadData;

@end

@protocol MAnimalViewModelDelegate

- (void)viewModel:(MAnimalsViewModel *)viewModel reloadRow:(NSInteger)row;

- (void)reloadDataWithViewModel:(MAnimalsViewModel *)viewModel;

@end

#import "MAnimalsViewModel.h"

#import "MAnimalsModel.h"

@interface MAnimalsViewModel()

@property (nonatomic,strong) MAnimalsModel *animalsModel;

@end

@implementation MAnimalsViewModel

- (instancetype)init {

self = [super init];

if (self) {

_animalsModel = [[MAnimalsModel alloc] init];

_animalsModel.delegate = self;

[self reloadData];

}

return self;

}

- (void)dealloc {

NSLog(@"%s",__func__);

}

- (MAnimalViewModel *)animalEntityWitIndexPath:(NSInteger)row {

MAnimalViewModel *viewModel = [_dataSource objectAtIndex:row];

if (_animalsModel.dataSource.count > row) {

MAnimalModel *model = [_animalsModel.dataSource objectAtIndex:row];

[_animalsModel downloadImageWtihModel:model];

}

return viewModel;

}

- (void)animalShowImage:(MAnimalModel *)animalModel row:(NSInteger)row {

MAnimalViewModel *viewModel = [_dataSource objectAtIndex:row];

viewModel.imageData = animalModel.imageData;

if (_delegate && [_delegate respondsToSelector:@selector(viewModel:reloadRow:)]) {

[_delegate viewModel:self reloadRow:row];

}

}

- (void)deleteWithRow:(NSInteger)row {

[_dataSource removeObjectAtIndex:row];

}

- (void)reloadData {

MAnimalViewModel *vieweModel = nil;

NSMutableArray *mutableArray = [NSMutableArray array];

for (MAnimalViewModel *eachViewModel in _animalsModel.dataSource) {

vieweModel = [[MAnimalViewModel alloc] init];

vieweModel.identifier = eachViewModel.identifier;

vieweModel.imageData = eachViewModel.imageData;

vieweModel.name = eachViewModel.name;

vieweModel.summary = eachViewModel.summary;

[mutableArray addObject:vieweModel];

}

_dataSource = mutableArray;

if (_delegate && [_delegate respondsToSelector:@selector(reloadDataWithViewModel:)]) {

[_delegate reloadDataWithViewModel:self];

}

}

@end

//------------------ViewModel-------------

@interface MAnimalViewModel : NSObject

@property (nonatomic,assign) NSInteger identifier;

@property (nonatomic,strong) NSData *imageData;

@property (nonatomic,copy) NSString *name;

@property (nonatomic,copy) NSString *summary;

@end

#import "MAnimalViewModel.h"

@implementation MAnimalViewModel

- (void)dealloc {

NSLog(@"%s",__func__);

}

@end

ViewController:

#import

@interface MAnimalViewController : UIViewController

@end

#import "MAnimalViewController.h"

#import "MAnimalTableView.h"

@interface MAnimalViewController ()

@end

@implementation MAnimalViewController

- (void)viewDidLoad {

[super viewDidLoad];

// Do any additional setup after loading the view.

self.title = @"MVVM";

self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Refresh"

style:UIBarButtonItemStylePlain

target:self

action:@selector(refreshAction)];

MAnimalTableView *tableView = [[MAnimalTableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];

self.view = tableView;

}

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

- (void)refreshAction {

MAnimalTableView *tableView = (MAnimalTableView *)self.view;

[tableView refreshData];

}

@end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值