Patrón de arquitectura MVP de iOS

¡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 .

MVPProgramació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 Presentery Modelcon Viewmenos funciones
  • Capacidad de prueba: debido a una Viewcapa funcionalmente simple, probar la lógica comercial se vuelve simple
  • Facilidad de uso: más código que usar MVCpatrones, pero MVPlos patrones tienen una estructura muy clara

Entonces, MVCla MVPdiferencia con y es que no hay comunicación directa entre MVPneutral Modely .View

Patrones de diseño

  • ModelLa capa no es solo para crear un objeto de datos, también debe contener solicitudes de red y Cachemanipulación de datos.
  • ViewLas capas son algo de encapsulación, reutilización
  • PresenterLa capa no involucra solicitudes de red y operaciones de datos , sino que es solo un puente para Cacheconstruir una Modelcapa 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 Presenteren
  • Ingrese la lógica Presenter, puede realizar pruebas unitarias lejos de la interfaz de usuario
  • Puede usar uno Presenerpara múltiples vistas sin cambiar Presenterla lógica. Esta función es muy útil porque la vista siempre cambia con más frecuencia que el modelo.

UIcon Modeldesacoplamiento

Cree LGProtocole implemente Cellla 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 Presentque implementa LGProtocolel 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 UIel Modelenlace de datos para el par. En el método interactivo del clic del botón, el delegatemétodo didClickNumllamado

- (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 VCcódigo , complete el enlace de datos del par medio LMDataSourcey la configuración delBlockCellUIModeldelegateindexPath

#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. CellPor ejemplo: el evento desencadenado didClickAddBtn, cuando num++es mayor que 5, la UIcapa solo muestra los dos primeros datos

Modificar LGProtocol, agregar UIinterfaz de evento de actualización

#import <Foundation/Foundation.h>

@protocol LGProtocol <NSObject>

- (void)didClickNum:(NSString *)num indexpath:(NSIndexPath *)indexpath;

- (void)reloadUI;

@end
复制代码

PresentEl método en la modificación didClickNum, aumenta nummás que 5, mantiene solo los dos primeros datos y llama delegateal reloadUImé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 LGProtocolactualizació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 UIy Modelconstruir 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 MVPcaso 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:

  • Cellencontrar formas más complejas
  • Usar demasiado delegatecó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 MVPla forma real de uso.

Supongo que te gusta

Origin juejin.im/post/7086831020703645710
Recomendado
Clasificación