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/