iOS 架构设计

讲讲 MVC、MVVM、MVP,以及你在项目里具体是怎么写的?

你自己用过哪些设计模式?

一般开始做一个项目,你的架构是如何思考的?

 

1:何为架构?

2:MVC - Apple版

3:MVC – 变种

4:MVP

5:MVVM

6: 三层架构

7: 四层架构

8: 设计模式

 

1:何为架构?

  • 架构(Architecture)

       软件开发中的设计方案

       类与类之间的关系、模块与模块之间的关系、客户端与服务端的关系 。架构可大可小。

 

  • 经常听到的架构名词

        MVC、MVP、MVVM、VIPER、CDD

        三层架构、四层架构

        ......

 

 

2:MVC - Apple版

Model-View-Controller

model和view不相互知道,只有vc知道并知道怎么使用。这里view的属性都在外面,进行赋值,并不会把model拿到view内部赋值。

优点:View、Model可以重复利用,可以独立使用。

缺点:Controller的代码过于臃肿

// 控制器 主要逻辑都在这里

#import "MJNewsViewController.h"
#import "MJNews.h"
#import "MJShop.h"

@interface MJNewsViewController ()
@property (strong, nonatomic) NSMutableArray *newsData;
@property (strong, nonatomic) NSMutableArray *shopData;
@end

@implementation MJNewsViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
//    [self loadNewsData];
    [self loadShopData];
}

- (void)loadShopData
{
    self.shopData = [NSMutableArray array];
    
    for (int i = 0; i < 20; i++) {
        MJShop *shop = [[MJShop alloc] init];
        shop.name = [NSString stringWithFormat:@"商品-%d", i];
        shop.price = [NSString stringWithFormat:@"¥19.%d", i];
        [self.shopData addObject:shop];
    }
}

- (void)loadNewsData
{
    self.newsData = [NSMutableArray array];
    
    for (int i = 0; i < 20; i++) {
        MJNews *news = [[MJNews alloc] init];
        news.title = [NSString stringWithFormat:@"news-title-%d", i];
        news.content = [NSString stringWithFormat:@"news-content-%d", i];
        [self.newsData addObject:news];
    }
}

#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.shopData.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NewsCell" forIndexPath:indexPath];
    
    MJShop *shop = self.shopData[indexPath.row];
    
    cell.detailTextLabel.text = shop.price;
    cell.textLabel.text = shop.name;
    
    return cell;
}

#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"1111");
}

@end

 

3:MVC – 变种

Model-View-Controller

一个view拥有一个模型,赋值逻辑在view内部进行处理,而且外部不知道view的内部空间和逻辑是什么。view做自己的事情。更具有封装性。

优点:对Controller进行瘦身,将View内部的细节封装起来了,外界不知道View内部的具体实现

缺点:View依赖于Model

 

view内部的逻辑和其余子view的事件 可以由控制器来控制操作

// 控制器

#import "ViewController.h"
#import "MJApp.h"
#import "MJAppView.h"

@interface ViewController () <MJAppViewDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建view
    MJAppView *appView = [[MJAppView alloc] init];
    appView.frame = CGRectMake(100, 100, 100, 150);
    appView.delegate = self;
    [self.view addSubview:appView];
    
    // 加载模型数据
    MJApp *app = [[MJApp alloc] init];
    app.name = @"QQ";
    app.image = @"QQ";
    
    // 设置数据到view上
    appView.app = app;
    
//    appView.iconView.image = [UIImage imageNamed:app.image];
//    appView.nameLabel.text = app.name;
}

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

@end



// view
@class MJApp, MJAppView;

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

@interface MJAppView : UIView
.......
@property (weak, nonatomic) id<MJAppViewDelegate> delegate;
@end


@class MJApp, MJAppView;

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

@interface MJAppView : UIView
@property (strong, nonatomic) MJApp *app;
@property (weak, nonatomic) id<MJAppViewDelegate> delegate;
@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)setApp:(MJApp *)app
{
    _app = app;
    
    self.iconView.image = [UIImage imageNamed:app.image];
    self.nameLabel.text = app.name;
}

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

@end

 

4:MVP

Model-View-Presenter

这种状态下,view也是不知道model的存在的

// 在vc中调用presenter

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

@interface ViewController ()
// 根据业务逻辑不同,这里可以设置不同的presenter
@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


// 模型
#import <Foundation/Foundation.h>

@interface MJApp : NSObject
@property (copy, nonatomic) NSString *name;
@property (copy, nonatomic) NSString *image;
@end


// appview

#import <UIKit/UIKit.h>

@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
#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


// presenter
#import <UIKit/UIKit.h>

@interface MJAppPresenter : NSObject
- (instancetype)initWithController:(UIViewController *)controller;
@end

#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

 

 

5:MVVM

Model-View-ViewModel

跟mvp很像的是:把view和模型的业务关系扔到viewmodel中,控制器只需要管理好viewmodel即可。

不太一样的地方是:属性监听绑定的问题。view可以监听viewmodel里面数据的改变,一旦数据改变,view显示的就会更新。

//控制器调用 当viewmodel多了就在这里多创建几个即可
#import "ViewController.h"
#import "MJAppViewModel.h"

@interface ViewController ()
@property (strong, nonatomic) MJAppViewModel *viewModel;
@end

@implementation ViewController

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


// viewmodel 比较重要的模块 管理着view和model的逻辑和创建 
#import <UIKit/UIKit.h>

@interface MJAppViewModel : NSObject
- (instancetype)initWithController:(UIViewController *)controller;
@end

#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;
        [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的处理,这里也非常重要,需要拿到及时更新的数据进行kvo通知在这里进行修改
#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;
    
    __weak typeof(self) waekSelf = self;
    // facebook的kvo。 监听 :FBKVOController
    [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

 

6: 三层架构

7: 四层架构

 

8: 设计模式

是类和类之间的关系,是一种思路

  • 设计模式(Design Pattern)

        是一套被反复使用、代码设计经验的总结

       使用设计模式的好处是:可重用代码、让代码更容易被他人理解、保证代码可靠性

       一般与编程语言无关,是一套比较成熟的编程思想

 

  • 设计模式可以分为三大类

        创建型模式:对象实例化的模式,用于解耦对象的实例化过程

                               单例模式、工厂方法模式,等等

        结构型模式:把类或对象结合在一起形成一个更大的结构

                               代理模式、适配器模式、组合模式、装饰模式,等等

        行为型模式:类或对象之间如何交互,及划分责任和算法

                               观察者模式(kvo底层)、命令模式、责任链模式,等等

 

 

  • 数据结构与算法

       严蔚敏,《数据结构》

     《大话数据结构与算法》

 

  • 网络

      《HTTP权威指南》

      《TCP/IP详解卷1:协议》

  • 架构与设计模式

       https://github.com/skyming/Trip-to-iOS-Design-Patterns

       https://design-patterns.readthedocs.io/zh_CN/latest/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值