iOS Architecture Design

Keywords: Mobile Programming github iOS Attribute

Tell me about MVC, MVVM, MVP, and how do you write it in the project?

What design patterns have you used?

Usually start a project. How do you think about your architecture?

 

1: What is the architecture?

2: MVC - Apple Edition

3: MVC - Variant

4: MVP

5: MVVM

6: Three-tier Architecture

7: Four-tier Architecture

8: Design Patterns

 

1: What is the architecture?

  • Architecture

Design scheme in software development

The relationship between class and class, module and module, client and server. Architecture can be large or small.

 

  • Architectural Nouns Frequently Heared

        MVC,MVP,MVVM,VIPER,CDD

Three-tier architecture, four-tier architecture

        ......

 

 

2: MVC - Apple Edition

Model-View-Controller

Models and views don't know each other, only vc knows and knows how to use them. Here, the view attributes are all outside, and the model is not assigned inside the view.

Advantages: View and Model can be reused and used independently.

Disadvantage: Controller's code is too bloated

// The main logic of the controller is here.

#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:@"commodity-%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 - Variant

Model-View-Controller

A view has a model, the assignment logic is processed inside the view, and the outside does not know what the internal space and logic of the view are. View does its own thing. More encapsulation.

Advantages: Thinning ontroller, encapsulating the details inside View, the outside world does not know the specific implementation inside View

Disadvantage: View depends on Model

 

Logic inside view and other sub-view events can be controlled by the controller.

// Controller

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

@interface ViewController () <MJAppViewDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // Create view
    MJAppView *appView = [[MJAppView alloc] init];
    appView.frame = CGRectMake(100, 100, 100, 150);
    appView.delegate = self;
    [self.view addSubview:appView];
    
    // Loading model data
    MJApp *app = [[MJApp alloc] init];
    app.name = @"QQ";
    app.image = @"QQ";
    
    // Set data to view
    appView.app = app;
    
//    appView.iconView.image = [UIImage imageNamed:app.image];
//    appView.nameLabel.text = app.name;
}

#pragma mark - MJAppViewDelegate
- (void)appViewDidClick:(MJAppView *)appView
{
    NSLog(@"The controller listened. appView Click");
}

@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

In this state, view does not know the existence of model.

// Call presenter in vc

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

@interface ViewController ()
// Depending on the business logic, different presenter can be set up here
@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


// Model
#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;
        
        // Create View
        MJAppView *appView = [[MJAppView alloc] init];
        appView.frame = CGRectMake(100, 100, 100, 150);
        appView.delegate = self;
        [controller.view addSubview:appView];
        
        // Loading model data
        MJApp *app = [[MJApp alloc] init];
        app.name = @"QQ";
        app.image = @"QQ";
        
        // Assignment data
        [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 Monitor appView Click");
}

@end

 

 

5: MVVM

Model-View-ViewModel

Similar to mvp, when the business relationship between view and model is thrown into the viewmodel, the controller only needs to manage the ViewModel well.

The difference is the problem of attribute listening binding. View can monitor the changes of data in the viewmodel, and once the data changes, the view display will be updated.

//Controller calls when there are more viewmodel s, just create a few more here.
#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


// The more important module of view model manages the logic and creation of view and 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;
        
        // Create View
        MJAppView *appView = [[MJAppView alloc] init];
        appView.frame = CGRectMake(100, 100, 100, 150);
        appView.delegate = self;
        appView.viewModel = self;
        [controller.view addSubview:appView];
        
        // Loading model data
        MJApp *app = [[MJApp alloc] init];
        app.name = @"QQ";
        app.image = @"QQ";
        
        // Setting data
        self.name = app.name;
        self.image = app.image;
    }
    return self;
}

#pragma mark - MJAppViewDelegate
- (void)appViewDidClick:(MJAppView *)appView
{
    NSLog(@"viewModel Monitor appView Click");
}

@end


// view processing, here is also very important, need to get timely updated data for kvo notification to modify here
#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's kvo. Monitoring: 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: Three-tier Architecture

7: Four-tier Architecture

 

8: Design Patterns

Is the relationship between class and class, is a way of thinking

  • Design Pattern s

Summary of experience in code design and reuse

The benefits of using design patterns are reusable code, making it easier for others to understand, and ensuring code reliability

Generally, it has nothing to do with programming language, and is a relatively mature programming idea.

 

  • Design patterns can be divided into three categories

Creative patterns: Object instantiation patterns used to decouple object instantiation processes

Singleton mode, factory method mode, etc.

Structural patterns: Combining classes or objects to form a larger structure

Agent mode, adapter mode, combination mode, decoration mode, etc.

Behavioral patterns: how classes or objects interact, and how responsibilities and algorithms are divided

Observer mode (bottom of kvo), command mode, responsibility chain mode, etc.

 

 

  • Data Structure and Algorithms

Yan Weimin, Data Structure

Dahua Data Structure and Algorithms

 

  • network

HTTP Authoritative Guide

TCP/IP Explanation Volume 1: Protocol

  • Architecture and Design Patterns

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

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

 

Posted by Teach on Sat, 02 Feb 2019 00:09:16 -0800