小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

iOS底層原理(十)架構設計

 新進小設計 2021-12-13

iOS中的幾種常用架構

MVC

MVC架構是以Model、Controller、View三者之間的關系來依賴的

Apple版的MVC

Apple最早的MVC的數(shù)據(jù)流向是以Controller為中心,在ModelView中間作為橋梁來銜接,而且ControllerModel、View之間的數(shù)據(jù)流向都是雙向的

-w651

例如,View上通過按鈕的點擊傳遞給Controller,Controller就去獲取數(shù)據(jù)來作為Model;Model的數(shù)據(jù)有了改變,又要通過展示到Controller展示到View

三者的交互過程中,ViewModel是互相沒有直接關聯(lián)的

在iOS程序中最常見的就是tableview的展示,見示例代碼

// LLNews
@interface LLNews : NSObject

@property (copy, nonatomic) NSString *title;
@property (copy, nonatomic) NSString *content;
@end

@implementation LLNews

@end

// LLNewsViewController
@interface LLNewsViewController : UITableViewController

@end

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

@implementation LLNewsViewController

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

- (void)loadNewsData
{
    self.newsData = [NSMutableArray array];
    
    for (int i = 0; i < 20; i++) {
        LLNews *news = [[LLNews 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.newsData.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NewsCell" forIndexPath:indexPath];
    
    LLNews *news = self.newsData[indexPath.row];
    
    cell.detailTextLabel.text = news.title;
    cell.textLabel.text = news.content;
    
    return cell;
}

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

@end

優(yōu)點:tableViewnewsData都是相對獨立的,可以復用
缺點:大量的賦值代碼會寫在Controller中,Controller變得過于臃腫

變種的MVC

變種后的MVC的數(shù)據(jù)流向,ControllerView還是相互作用的,Controller也還是會去獲取數(shù)據(jù)來作為Model;不同的是View也可以直接持有Model了,三者之間互相都有了交互

-w502

下面我們用示例代碼來說明三者之間的具體關系

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

@implementation LLApp

@end

// LLAppView
@class LLApp, LLAppView;

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

@interface LLAppView : UIView
@property (strong, nonatomic) LLApp *app;
@property (weak, nonatomic) id<LLAppViewDelegate> delegate;
@end

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

@implementation LLAppView

- (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:(LLApp *)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

// ViewController
@interface ViewController () <LLAppViewDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 創(chuàng)建view
    LLAppView *appView = [[LLAppView alloc] init];
    appView.frame = CGRectMake(100, 100, 100, 150);
    appView.delegate = self;
    [self.view addSubview:appView];
    
    // 加載模型數(shù)據(jù)
    LLApp *app = [[LLApp alloc] init];
    app.name = @"QQ";
    app.image = @"QQ";
    
    // 設置數(shù)據(jù)到view上
    appView.app = app;
}

#pragma mark - LLAppViewDelegate
- (void)appViewDidClick:(LLAppView *)appView
{
    NSLog(@"控制器監(jiān)聽到了appView的點擊");
}

@end

優(yōu)點:Controller會相對減負,減少View的數(shù)據(jù)賦值代碼,而且外部不用關心View的屬性以及做了什么

缺點:ViewModel耦合性太高了,會造成相互依賴,不能再分別單獨使用了,復用性降低了

MVP

MVP架構是以Model、Presenter、View三者之間的關系來依賴的

Presenter更像是替代了Controller來作為ModelView之間的橋梁,而Controller只需要管理Presenter就可以了

-w611

我們借由上面的示例來做下調整,示例代碼如下

LLAppLLAppView基本不變

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

@implementation LLApp

@end

// LLAppView
@class LLAppView;

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

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

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

@implementation LLAppView

- (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和抽取后的Controller代碼如下

// LLAppPresenter
@interface LLAppPresenter : NSObject

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

@interface LLAppPresenter() <LLAppViewDelegate>

@property (weak, nonatomic) UIViewController *controller;
@end

@implementation LLAppPresenter

- (instancetype)initWithController:(UIViewController *)controller
{
    if (self = [super init]) {
        self.controller = controller;
        
        // 創(chuàng)建View
        LLAppView *appView = [[LLAppView alloc] init];
        appView.frame = CGRectMake(100, 100, 100, 150);
        appView.delegate = self;
        [controller.view addSubview:appView];
        
        // 加載模型數(shù)據(jù)
        LLApp *app = [[LLApp alloc] init];
        app.name = @"QQ";
        app.image = @"QQ";
        
        // 賦值數(shù)據(jù)
        [appView setName:app.name andImage:app.image];
    }
    return self;
}

#pragma mark - MJAppViewDelegate
- (void)appViewDidClick:(LLAppView *)appView
{
    NSLog(@"presenter 監(jiān)聽了 appView 的點擊");
}

@end

// ViewController
@interface ViewController ()

@property (strong, nonatomic) LLAppPresenter *presenter;
@end

@implementation ViewController

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

@end

優(yōu)點:

  • 每個Presenter對應著各自的ModelView
  • ModelView也更加的獨立性、可復用
  • Controller里變得更簡潔,只需要管理不同的Presenter就可以

MVVM

MVVM架構是以Model、ViewModel、View三者之間的關系來依賴的,其中的View包括了ViewController

ViewModel的作用是將Controller的業(yè)務邏輯抽取出來,并且把ModelView做一個綁定關系

-w693

我們將MVC的tableview的示例做了更改后,代碼如下

// LLNews
@interface LLNews : NSObject
@property (copy, nonatomic) NSString *title;
@property (copy, nonatomic) NSString *content;
@end

@implementation LLNews

@end

// LLNewsViewModel
@interface LLNewsViewModel : NSObject

- (void)loadNewsData:(void (^)(NSArray *newsData))completion;
@end

@implementation LLNewsViewModel

- (void)loadNewsData:(void (^)(NSArray *))completion
{
    if (!completion) return;
    
    NSMutableArray *newsData = [NSMutableArray array];
    for (int i = 0; i < 20; i++) {
        // 發(fā)送網(wǎng)絡請求、字典轉模型
        LLNews *news = [[LLNews alloc] init];
        news.title = [NSString stringWithFormat:@"news-title-%d", i];
        news.content = [NSString stringWithFormat:@"news-content-%d", i];
        [newsData addObject:news];
    }
    
    completion(newsData);
}

@end

// LLNewsViewController
@interface LLNewsViewController ()
@property (nonatomic, strong) LLNewsViewModel *newsVM;
@property (nonatomic, assign) NSArray *newsData;
@end

@implementation LLNewsViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.newsVM = [[LLNewsViewModel alloc] init];
    [self.newsVM loadNewsData:^(NSArray *newsData) {
        self.newsData = newsData;
    }];
}

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NewsCell" forIndexPath:indexPath];
    
    LLNews *news = self.newsData[indexPath.row];
    
    cell.detailTextLabel.text = news.title;
    cell.textLabel.text = news.content;
    
    return cell;
}

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

@end

優(yōu)點:Controller可以不用寫邏輯代碼,相對減輕負擔,MVVM可以結合一些響應式框架來更簡便使用

架構分層

一般我們經(jīng)常會分為三層架構,分別是界面層、業(yè)務層、數(shù)據(jù)層

MVC、MVP、MVVM這幾種架構都是建立于界面層來討論的

架構分層的目的就是為了降低耦合性,易于維護和開發(fā)

設計模式

什么是設計模式

設計模式(Design Pattern)是一套被反復使用、代碼設計經(jīng)驗的總結
使用設計模式的好處是:可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性
一般與編程語言無關,是一套比較成熟的編程思想### 設計模式的幾大類設計模式可以分為三大類- 創(chuàng)建型模式:對象實例化的模式,用于解耦對象的實例化過程 - 單例模式、工廠方法模式,等等- 結構型模式:把類或對象結合在一起形成一個更大的結構 - 代理模式、適配器模式、組合模式、裝飾模式,等等- 行為型模式:類或對象之間如何交互,及劃分責任和算法 - 觀察者模式、命令模式、責任鏈模式,等等具體概述之后再詳細討論

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多