iOS底层day12 - 架构设计

MVC - Apple

2927534-eedfd13d34a34fe4.png
MVC-apple

控制器作为 ModelView中间的协调者,Model负责数据记录,View负责试图,而在控制器中创建View,给View赋值Model数据,协调双方
以TableView为栗子:


#import "TableViewController1.h"
#import "MJModel.h"

@interface TableViewController1 ()

@property (nonatomic,strong)NSMutableArray *datas;
@end
@implementation TableViewController1

- (void)viewDidLoad {
    [super viewDidLoad];
    self.datas = [NSMutableArray array];
    for (int i = 0; i < 20; i++ ) {
        MJModel *model = [[MJModel alloc] init];
        model.title = [NSString stringWithFormat:@"title --- %d",i];
        model.detail_title = [NSString stringWithFormat:@"detail_title --- %d",i];
        [self.datas addObject:model];
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
#warning Incomplete implementation, return the number of rows
    return self.datas.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MJCell" forIndexPath:indexPath];
    MJModel *model = self.datas[indexPath.row];
    cell.textLabel.text = model.title;
    cell.detailTextLabel.text = model.detail_title;
    
    return cell;
}
@end

这里,控制器协调View和Model,最终展示TableVIew
Apple的MVC的好处就是Model和View耦合性低,但是控制器的代码臃肿

MVC - 变种

2927534-a6f8a9013330bc60.png
MVC变种
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MJCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MJCell" forIndexPath:indexPath];
    MJModel *model = self.datas[indexPath.row];
    cell.model = model;
//    cell.textLabel.text = model.title;
//    cell.detailTextLabel.text = model.detail_title;
//
    return cell;
}
#import <UIKit/UIKit.h>
#import "MJModel.h"
@interface MJCell : UITableViewCell
@property (nonatomic,strong)MJModel *model;

@end
#import "MJCell.h"

@implementation MJCell

- (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
}

- (void)setModel:(MJModel *)model {
    _model = model;
    self.textLabel.text = model.title;
    self.detailTextLabel.text = model.detail_title;
}
@end

MVC的变种使控制器代码变得简单一点,但是增加了View和控制器的关系,View依赖与Model的结构

MVP

2927534-335d3166434a34ad.png
image.png

类似于Apple的MVC,只是把让 presenter拥有控制器,并把业务逻辑写到 presenter
这里,控制器加载 presenter

#import "ViewController.h"
#import "MJAppPresenter.h"

@interface ViewController ()
@property (strong, nonatomic) MJAppPresenter *presenter;
//@property (strong, nonatomic) MJOtherPresenter *presenter1;
//@property (strong, nonatomic) MJNewsPresenter *presenter2;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.presenter = [[MJAppPresenter alloc] initWithController:self];
}
@end

Presenter实现:


#import "MJAppPresenter.h"
#import "MJApp.h"
#import "MJAppView.h"

@interface MJAppPresenter() <MJAppViewDelegate>
@property (weak, nonatomic) UIViewController *controller;
@end

@implementation MJAppPresenter

- (instancetype)initWithController:(UIViewController *)controller
{
    if (self = [super init]) {
        self.controller = controller;
        
        // 创建View
        MJAppView *appView = [[MJAppView alloc] init];
        appView.frame = CGRectMake(100, 100, 100, 150);
        appView.delegate = self;
        [controller.view addSubview:appView];
        
        // 加载模型数据
        MJApp *app = [[MJApp alloc] init];
        app.name = @"QQ";
        app.image = @"QQ";
        
        // 赋值数据
        [appView setName:app.name andImage:app.image];
//        appView.iconView.image = [UIImage imageNamed:app.image];
//        appView.nameLabel.text = app.name;
    }
    return self;
}

#pragma mark - MJAppViewDelegate
- (void)appViewDidClick:(MJAppView *)appView
{
    NSLog(@"presenter 监听了 appView 的点击");
}

@end

View 声明

@class MJAppView;

@protocol MJAppViewDelegate <NSObject>
@optional
- (void)appViewDidClick:(MJAppView *)appView;
@end

@interface MJAppView : UIView
- (void)setName:(NSString *)name andImage:(NSString *)image;
@property (weak, nonatomic) id<MJAppViewDelegate> delegate;
@end

View 实现


#import "MJAppView.h"

@interface MJAppView()
@property (weak, nonatomic) UIImageView *iconView;
@property (weak, nonatomic) UILabel *nameLabel;
@end

@implementation MJAppView

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        UIImageView *iconView = [[UIImageView alloc] init];
        iconView.frame = CGRectMake(0, 0, 100, 100);
        [self addSubview:iconView];
        _iconView = iconView;
        
        UILabel *nameLabel = [[UILabel alloc] init];
        nameLabel.frame = CGRectMake(0, 100, 100, 30);
        nameLabel.textAlignment = NSTextAlignmentCenter;
        [self addSubview:nameLabel];
        _nameLabel = nameLabel;
    }
    return self;
}

- (void)setName:(NSString *)name andImage:(NSString *)image
{
    _iconView.image = [UIImage imageNamed:image];
    _nameLabel.text = name;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if ([self.delegate respondsToSelector:@selector(appViewDidClick:)]) {
        [self.delegate appViewDidClick:self];
    }
}

@end

MVVM

2927534-94ccf512caa5592b.png
MVVM

MVVM 与MVP类似,用ViewModel代替了Presenter,而MVVM的核心在于让View和ViewModel双向绑定,让View监听ViewModel的属性改变,以实现视图更新
ViewModel:

#import "MJAppViewModel.h"
#import "MJApp.h"
#import "MJAppView.h"

@interface MJAppViewModel() <MJAppViewDelegate>
@property (weak, nonatomic) UIViewController *controller;
@property (copy, nonatomic) NSString *name;
@property (copy, nonatomic) NSString *image;
@end

@implementation MJAppViewModel

- (instancetype)initWithController:(UIViewController *)controller
{
    if (self = [super init]) {
        self.controller = controller;
        
        // 创建View
        MJAppView *appView = [[MJAppView alloc] init];
        appView.frame = CGRectMake(100, 100, 100, 150);
        appView.delegate = self;
        appView.viewModel = self;  // 让View持有ViewModel
        [controller.view addSubview:appView];
        
        // 加载模型数据
        MJApp *app = [[MJApp alloc] init];
        app.name = @"QQ";
        app.image = @"QQ";
        
        // 设置数据
        self.name = app.name;
        self.image = app.image;
    }
    return self;
}

#pragma mark - MJAppViewDelegate
- (void)appViewDidClick:(MJAppView *)appView
{
    NSLog(@"viewModel 监听了 appView 的点击");
}

@end

VIew:

#import <UIKit/UIKit.h>

@class MJAppView, MJAppViewModel;

@protocol MJAppViewDelegate <NSObject>
@optional
- (void)appViewDidClick:(MJAppView *)appView;
@end

@interface MJAppView : UIView
@property (weak, nonatomic) MJAppViewModel *viewModel;
@property (weak, nonatomic) id<MJAppViewDelegate> delegate;
@end
#import "MJAppView.h"
#import "NSObject+FBKVOController.h"

@interface MJAppView()
@property (weak, nonatomic) UIImageView *iconView;
@property (weak, nonatomic) UILabel *nameLabel;
@end

@implementation MJAppView

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        UIImageView *iconView = [[UIImageView alloc] init];
        iconView.frame = CGRectMake(0, 0, 100, 100);
        [self addSubview:iconView];
        _iconView = iconView;
        
        UILabel *nameLabel = [[UILabel alloc] init];
        nameLabel.frame = CGRectMake(0, 100, 100, 30);
        nameLabel.textAlignment = NSTextAlignmentCenter;
        [self addSubview:nameLabel];
        _nameLabel = nameLabel;
    }
    return self;
}

- (void)setViewModel:(MJAppViewModel *)viewModel
{
    _viewModel = viewModel;
    
// 监听ViewModel属性改变 这里使用了一个第三方faceBook 的KVO
    __weak typeof(self) waekSelf = self;
    [self.KVOController observe:viewModel keyPath:@"name" options:NSKeyValueObservingOptionNew block:^(id  _Nullable observer, id  _Nonnull object, NSDictionary<NSKeyValueChangeKey,id> * _Nonnull change) {
        waekSelf.nameLabel.text = change[NSKeyValueChangeNewKey];
    }];
    
    [self.KVOController observe:viewModel keyPath:@"image" options:NSKeyValueObservingOptionNew block:^(id  _Nullable observer, id  _Nonnull object, NSDictionary<NSKeyValueChangeKey,id> * _Nonnull change) {
        waekSelf.iconView.image = [UIImage imageNamed:change[NSKeyValueChangeNewKey]];
    }];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if ([self.delegate respondsToSelector:@selector(appViewDidClick:)]) {
        [self.delegate appViewDidClick:self];
    }
}

@end

分层架构

三层架构


2927534-eea3aac58913b657.png
image.png

四层架构


2927534-b978572bd7277c21.png
image.png

Controller

#import "ViewController.h"
#import "MJNewsService.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [MJNewsService loadNews:@{} success:^(NSArray *newsData) {
        
    } failure:^(NSError *error) {
        
    }];
}


@end

Service

#import <Foundation/Foundation.h>

@interface MJNewsService : NSObject
+ (void)loadNews:(NSDictionary *)params success:(void (^)(NSArray *newsData))success failure:(void (^)(NSError *error))failure;
@end
#import "MJNewsService.h"
#import "MJHTTPTool.h"
#import "MJDBTool.h"

@implementation MJNewsService

+ (void)loadNews:(NSDictionary *)params success:(void (^)(NSArray *newsData))success failure:(void (^)(NSError *error))failure
{
    // 先取出本地数据
//    [MJDBTool loadLocalData....];
    
    // 如果没有本地数据,就加载网络数据
//    [MJHTTPTool GET:@"xxxx" params:nil success:^(id result) {
//        success(array);
//    } failure:failure];
}
@end

Data

#import <Foundation/Foundation.h>

@interface MJHTTPTool : NSObject
+ (void)GET:(NSString *)URL params:(NSDictionary *)params success:(void (^)(id result))success failure:(void (^)(NSError *error))failure;
@end
#import "MJHTTPTool.h"

@implementation MJHTTPTool

+ (void)GET:(NSString *)URL params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSError *))failure
{
    // 调用AFN
}

@end

设计模式

2927534-1e466fbd63c6d296.png
image.png

推荐:


2927534-95e5f709c6733ac8.png
image.png
到这里,就全部告一段落啦,希望看完的你有所收获 :) thanks

猜你喜欢

转载自blog.csdn.net/weixin_33845477/article/details/87243069