¡Acostúmbrate a escribir juntos! Este es el noveno día de mi participación en el "Nuggets Daily New Plan · April Update Challenge", haz clic para ver los detalles del evento .
MVP
Programación Orientada a Protocolos, es decir Model View Presenter
(Coordinador de Vista de Modelo).
rasgo
- Amortización de tareas: Divide las tareas más importantes en
Presenter
yModel
conView
menos funciones - Capacidad de prueba: debido a una
View
capa funcionalmente simple, probar la lógica comercial se vuelve simple - Facilidad de uso: más código que usar
MVC
patrones, peroMVP
los patrones tienen una estructura muy clara
Entonces, MVC
la MVP
diferencia con y es que no hay comunicación directa entre MVP
neutral Model
y .View
Patrones de diseño
Model
La capa no es solo para crear un objeto de datos, también debe contener solicitudes de red yCache
manipulación de datos.View
Las capas son algo de encapsulación, reutilizaciónPresenter
La capa no involucra solicitudes de red y operaciones de datos , sino que es solo un puente paraCache
construir unaModel
capa y una capa.View
Ventaja
- El modelo está completamente separado de la vista, modifique la vista sin afectar el modelo
- Los modelos se pueden usar de manera más eficiente porque todas las interacciones están
Presenter
en - Ingrese la lógica
Presenter
, puede realizar pruebas unitarias lejos de la interfaz de usuario - Puede usar uno
Presener
para múltiples vistas sin cambiarPresenter
la lógica. Esta función es muy útil porque la vista siempre cambia con más frecuencia que el modelo.
UI
con Model
desacoplamiento
Cree LGProtocol
e implemente Cell
la interfaz de eventos del clic del botón en el medio
#import <Foundation/Foundation.h>
@protocol LGProtocol <NSObject>
- (void)didClickNum:(NSString *)num indexpath:(NSIndexPath *)indexpath;
@end
复制代码
En , el método Present
que implementa LGProtocol
el protocolodidClickNum
#import <Foundation/Foundation.h>
#import "Model.h"
#import "LGProtocol.h"
#import <YYKit.h>
@interface Present : NSObject<LGProtocol>
@property (nonatomic, strong) NSMutableArray *dataArray;
@property (nonatomic, weak) id<LGProtocol> delegate;
@end
@implementation Present
- (instancetype)init{
if (self = [super init]) {
[self loadData];
}
return self;
}
- (void)loadData{
NSArray *temArray =
@[
@{@"name":@"HK",@"imageUrl":@"http://HK",@"num":@"99"},
@{@"name":@"KD",@"imageUrl":@"http://KD",@"num":@"99"},
@{@"name":@"CC",@"imageUrl":@"http://CC",@"num":@"99"},
@{@"name":@"KC",@"imageUrl":@"http://KC",@"num":@"59"},
@{@"name":@"LA",@"imageUrl":@"http://LA",@"num":@"24"}];
for (int i = 0; i<temArray.count; i++) {
Model *m = [Model modelWithDictionary:temArray[i]];
[self.dataArray addObject:m];
}
}
#pragma mark -LGProtocol
- (void)didClickNum:(NSString *)num indexpath:(NSIndexPath *)indexpath{
@synchronized (self) {
if (indexpath.row < self.dataArray.count) {
Model *model = self.dataArray[indexpath.row];
model.num = num;
}
}
}
#pragma mark - lazy
- (NSMutableArray *)dataArray{
if (!_dataArray) {
_dataArray = [NSMutableArray arrayWithCapacity:10];
}
return _dataArray;
}
@end
复制代码
En MVCTableViewCell
, elimine UI
el Model
enlace de datos para el par. En el método interactivo del clic del botón, el delegate
método didClickNum
llamado
- (void)didClickAddBtn:(UIButton *)sender{
self.num++;
}
- (void)setNum:(int)num{
_num = num;
self.numLabel.text = [NSString stringWithFormat:@"%d",self.num];
// 发出响应 model delegate UI
if (self.delegate && [self.delegate respondsToSelector:@selector(didClickNum:indexpath:)]) {
[self.delegate didClickNum:self.numLabel.text indexpath:self.indexPath];
}
}
// 删除UI对Model的数据绑定
//- (void)setModel:(Model *)model{
// _model = model;
// self.numLabel.text = model.num;
// self.nameLabel.text = model.name;
//}
复制代码
Vaya al VC
código , complete el enlace de datos del par medio LMDataSource
y la configuración delBlock
Cell
UI
Model
delegate
indexPath
#import "MVCViewController.h"
#import "LMDataSource.h"
#import "MVCTableViewCell.h"
#import "Present.h"
#import "Model.h"
#import "LGView.h"
@interface MVCViewController ()
@property (nonatomic, strong) LGView *lgView;
@property (nonatomic, strong) LMDataSource *dataSource;
@property (nonatomic, strong) Present *pt;
@end
@implementation MVCViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 建立关系
self.view = self.lgView;
[self.dataSource setDataArray:self.pt.dataArray];
[self.lgView setDataSource:self.dataSource];
}
#pragma mark - lazy
// UI布局代码
- (LGView *)lgView{
if(!_lgView){
_lgView = [[LGView alloc] initWithFrame:self.view.bounds];
}
return _lgView;
}
// 数据提供层
- (Present *)pt{
if(!_pt){
_pt = [[Present alloc] init];
}
return _pt;
}
// 数据代理层
- (LMDataSource *)dataSource{
if(!_dataSource){
__weak typeof(self) weakSelf = self;
_dataSource = [[LMDataSource alloc] initWithIdentifier:[MVCTableViewCell reuserId] configureBlock:^(MVCTableViewCell *cell, Model *model, NSIndexPath *indexPath) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
cell.numLabel.text = model.num;
cell.nameLabel.text = model.name;
cell.delegate = strongSelf.pt;
cell.indexPath = indexPath;
}];
}
return _dataSource;
}
@end
复制代码
unión bidireccional
Cuando se encuentran los siguientes requisitos durante el desarrollo, se requiere un enlace bidireccional entre la interfaz de usuario y el modelo. Cell
Por ejemplo: el evento desencadenado didClickAddBtn
, cuando num++
es mayor que 5
, la UI
capa solo muestra los dos primeros datos
Modificar LGProtocol
, agregar UI
interfaz de evento de actualización
#import <Foundation/Foundation.h>
@protocol LGProtocol <NSObject>
- (void)didClickNum:(NSString *)num indexpath:(NSIndexPath *)indexpath;
- (void)reloadUI;
@end
复制代码
Present
El método en la modificación didClickNum
, aumenta num
más que 5
, mantiene solo los dos primeros datos y llama delegate
al reloadUI
método para actualizarUI
- (void)didClickNum:(NSString *)num indexpath:(NSIndexPath *)indexpath{
@synchronized (self) {
if (indexpath.row < self.dataArray.count) {
Model *model = self.dataArray[indexpath.row];
model.num = num;
if ([num intValue] > 5) {
[self.dataArray removeAllObjects];
NSArray *temArray =
@[
@{@"name":@"HK",@"imageUrl":@"http://HK",@"num":@"99"},
@{@"name":@"KC",@"imageUrl":@"http://KC",@"num":@"99"}];
for (int i = 0; i<temArray.count; i++) {
Model *m = [Model modelWithDictionary:temArray[i]];
[self.dataArray addObject:m];
}
if (self.delegate && [self.delegate respondsToSelector:@selector(reloadUI)]) {
[self.delegate reloadUI];
}
}
}
}
}
复制代码
Modificar LGView
, implementar el método de LGProtocol
actualización del protocolo.UI
#import <UIKit/UIKit.h>
#import "MVCTableViewCell.h"
#import "LGProtocol.h"
@interface LGView : UIView<LGProtocol>
@property (nonatomic, strong) UITableView *tableView;
- (void)setDataSource:(id<UITableViewDataSource>)dataSource;
@end
@implementation LGView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self addSubview:self.tableView];
}
return self;
}
- (void)setDataSource:(id<UITableViewDataSource>)dataSource{
self.tableView.dataSource = dataSource;
}
- (void)reloadUI{
[self.tableView reloadData];
}
- (UITableView *)tableView{
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:self.frame style:UITableViewStylePlain];
_tableView.tableFooterView = [UIView new];
_tableView.backgroundColor = [UIColor whiteColor];
[_tableView registerClass:[MVCTableViewCell class] forCellReuseIdentifier:[MVCTableViewCell reuserId]];
}
return _tableView;
}
@end
复制代码
Modificar MVCViewController
, establecer UI
y Model
construir una relación
- (void)viewDidLoad {
[super viewDidLoad];
// 建立关系
self.view = self.lgView;
[self.dataSource setDataArray:self.pt.dataArray];
[self.lgView setDataSource:self.dataSource];
//将UI和Model建立关系
self.pt.delegate = self.lgView;
}
复制代码
Para el MVP
caso simple anterior, todavía hay muchos defectos. Este tipo de código rudimentario es difícil de satisfacer incluso las necesidades comunes en el desarrollo
Por ejemplo las siguientes situaciones:
Cell
encontrar formas más complejas- Usar demasiado
delegate
código iso-pegamento - Cuando el nivel del módulo es más profundo, es difícil comunicarse entre sí
Por lo tanto, en respuesta a los problemas anteriores, sino también para introducir MVP
la forma real de uso.