经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » iOS » 查看文章
iOS底层原理(十)架构设计
来源:cnblogs  作者:FunkyRay  时间:2021/3/8 11:48:56  对本文有异议

iOS中的几种常用架构

MVC

MVC架构是以Model、Controller、View三者之间的关系来依赖的

Apple版的MVC

Apple最早的MVC的数据流向是以Controller为中心,在ModelView中间作为桥梁来衔接,而且ControllerModel、View之间的数据流向都是双向的

-w651

例如,View上通过按钮的点击传递给ControllerController就去获取数据来作为ModelModel的数据有了改变,又要通过展示到Controller展示到View

三者的交互过程中,ViewModel是互相没有直接关联的

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

  1. // LLNews
  2. @interface LLNews : NSObject
  3. @property (copy, nonatomic) NSString *title;
  4. @property (copy, nonatomic) NSString *content;
  5. @end
  6. @implementation LLNews
  7. @end
  8. // LLNewsViewController
  9. @interface LLNewsViewController : UITableViewController
  10. @end
  11. @interface LLNewsViewController ()
  12. @property (strong, nonatomic) NSMutableArray *newsData;
  13. @end
  14. @implementation LLNewsViewController
  15. - (void)viewDidLoad {
  16. [super viewDidLoad];
  17. [self loadNewsData];
  18. }
  19. - (void)loadNewsData
  20. {
  21. self.newsData = [NSMutableArray array];
  22. for (int i = 0; i < 20; i++) {
  23. LLNews *news = [[LLNews alloc] init];
  24. news.title = [NSString stringWithFormat:@"news-title-%d", i];
  25. news.content = [NSString stringWithFormat:@"news-content-%d", i];
  26. [self.newsData addObject:news];
  27. }
  28. }
  29. #pragma mark - Table view data source
  30. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  31. return self.newsData.count;
  32. }
  33. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  34. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NewsCell" forIndexPath:indexPath];
  35. LLNews *news = self.newsData[indexPath.row];
  36. cell.detailTextLabel.text = news.title;
  37. cell.textLabel.text = news.content;
  38. return cell;
  39. }
  40. #pragma mark - UITableViewDelegate
  41. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  42. {
  43. NSLog(@"1111");
  44. }
  45. @end

优点:tableViewnewsData都是相对独立的,可以复用
缺点:大量的赋值代码会写在Controller中,Controller变得过于臃肿

变种的MVC

变种后的MVC的数据流向,ControllerView还是相互作用的,Controller也还是会去获取数据来作为Model;不同的是View也可以直接持有Model了,三者之间互相都有了交互

-w502

下面我们用示例代码来说明三者之间的具体关系

  1. // LLApp
  2. @interface LLApp : NSObject
  3. @property (copy, nonatomic) NSString *name;
  4. @property (copy, nonatomic) NSString *image;
  5. @end
  6. @implementation LLApp
  7. @end
  8. // LLAppView
  9. @class LLApp, LLAppView;
  10. @protocol LLAppViewDelegate <NSObject>
  11. @optional
  12. - (void)appViewDidClick:(LLAppView *)appView;
  13. @end
  14. @interface LLAppView : UIView
  15. @property (strong, nonatomic) LLApp *app;
  16. @property (weak, nonatomic) id<LLAppViewDelegate> delegate;
  17. @end
  18. @interface LLAppView()
  19. @property (weak, nonatomic) UIImageView *iconView;
  20. @property (weak, nonatomic) UILabel *nameLabel;
  21. @end
  22. @implementation LLAppView
  23. - (instancetype)initWithFrame:(CGRect)frame
  24. {
  25. if (self = [super initWithFrame:frame]) {
  26. UIImageView *iconView = [[UIImageView alloc] init];
  27. iconView.frame = CGRectMake(0, 0, 100, 100);
  28. [self addSubview:iconView];
  29. _iconView = iconView;
  30. UILabel *nameLabel = [[UILabel alloc] init];
  31. nameLabel.frame = CGRectMake(0, 100, 100, 30);
  32. nameLabel.textAlignment = NSTextAlignmentCenter;
  33. [self addSubview:nameLabel];
  34. _nameLabel = nameLabel;
  35. }
  36. return self;
  37. }
  38. - (void)setApp:(LLApp *)app
  39. {
  40. _app = app;
  41. self.iconView.image = [UIImage imageNamed:app.image];
  42. self.nameLabel.text = app.name;
  43. }
  44. - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
  45. {
  46. if ([self.delegate respondsToSelector:@selector(appViewDidClick:)]) {
  47. [self.delegate appViewDidClick:self];
  48. }
  49. }
  50. @end
  51. // ViewController
  52. @interface ViewController () <LLAppViewDelegate>
  53. @end
  54. @implementation ViewController
  55. - (void)viewDidLoad {
  56. [super viewDidLoad];
  57. // 创建view
  58. LLAppView *appView = [[LLAppView alloc] init];
  59. appView.frame = CGRectMake(100, 100, 100, 150);
  60. appView.delegate = self;
  61. [self.view addSubview:appView];
  62. // 加载模型数据
  63. LLApp *app = [[LLApp alloc] init];
  64. app.name = @"QQ";
  65. app.image = @"QQ";
  66. // 设置数据到view上
  67. appView.app = app;
  68. }
  69. #pragma mark - LLAppViewDelegate
  70. - (void)appViewDidClick:(LLAppView *)appView
  71. {
  72. NSLog(@"控制器监听到了appView的点击");
  73. }
  74. @end

优点:Controller会相对减负,减少View的数据赋值代码,而且外部不用关心View的属性以及做了什么

缺点:ViewModel耦合性太高了,会造成相互依赖,不能再分别单独使用了,复用性降低了

MVP

MVP架构是以Model、Presenter、View三者之间的关系来依赖的

Presenter更像是替代了Controller来作为ModelView之间的桥梁,而Controller只需要管理Presenter就可以了

-w611

我们借由上面的示例来做下调整,示例代码如下

LLAppLLAppView基本不变

  1. // LLApp
  2. @interface LLApp : NSObject
  3. @property (copy, nonatomic) NSString *name;
  4. @property (copy, nonatomic) NSString *image;
  5. @end
  6. @implementation LLApp
  7. @end
  8. // LLAppView
  9. @class LLAppView;
  10. @protocol LLAppViewDelegate <NSObject>
  11. @optional
  12. - (void)appViewDidClick:(LLAppView *)appView;
  13. @end
  14. @interface LLAppView : UIView
  15. - (void)setName:(NSString *)name andImage:(NSString *)image;
  16. @property (weak, nonatomic) id<LLAppViewDelegate> delegate;
  17. @end
  18. @interface LLAppView()
  19. @property (weak, nonatomic) UIImageView *iconView;
  20. @property (weak, nonatomic) UILabel *nameLabel;
  21. @end
  22. @implementation LLAppView
  23. - (instancetype)initWithFrame:(CGRect)frame
  24. {
  25. if (self = [super initWithFrame:frame]) {
  26. UIImageView *iconView = [[UIImageView alloc] init];
  27. iconView.frame = CGRectMake(0, 0, 100, 100);
  28. [self addSubview:iconView];
  29. _iconView = iconView;
  30. UILabel *nameLabel = [[UILabel alloc] init];
  31. nameLabel.frame = CGRectMake(0, 100, 100, 30);
  32. nameLabel.textAlignment = NSTextAlignmentCenter;
  33. [self addSubview:nameLabel];
  34. _nameLabel = nameLabel;
  35. }
  36. return self;
  37. }
  38. - (void)setName:(NSString *)name andImage:(NSString *)image
  39. {
  40. _iconView.image = [UIImage imageNamed:image];
  41. _nameLabel.text = name;
  42. }
  43. - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
  44. {
  45. if ([self.delegate respondsToSelector:@selector(appViewDidClick:)]) {
  46. [self.delegate appViewDidClick:self];
  47. }
  48. }
  49. @end

多出来的Presenter和抽取后的Controller代码如下

  1. // LLAppPresenter
  2. @interface LLAppPresenter : NSObject
  3. - (instancetype)initWithController:(UIViewController *)controller;
  4. @end
  5. @interface LLAppPresenter() <LLAppViewDelegate>
  6. @property (weak, nonatomic) UIViewController *controller;
  7. @end
  8. @implementation LLAppPresenter
  9. - (instancetype)initWithController:(UIViewController *)controller
  10. {
  11. if (self = [super init]) {
  12. self.controller = controller;
  13. // 创建View
  14. LLAppView *appView = [[LLAppView alloc] init];
  15. appView.frame = CGRectMake(100, 100, 100, 150);
  16. appView.delegate = self;
  17. [controller.view addSubview:appView];
  18. // 加载模型数据
  19. LLApp *app = [[LLApp alloc] init];
  20. app.name = @"QQ";
  21. app.image = @"QQ";
  22. // 赋值数据
  23. [appView setName:app.name andImage:app.image];
  24. }
  25. return self;
  26. }
  27. #pragma mark - MJAppViewDelegate
  28. - (void)appViewDidClick:(LLAppView *)appView
  29. {
  30. NSLog(@"presenter 监听了 appView 的点击");
  31. }
  32. @end
  33. // ViewController
  34. @interface ViewController ()
  35. @property (strong, nonatomic) LLAppPresenter *presenter;
  36. @end
  37. @implementation ViewController
  38. - (void)viewDidLoad {
  39. [super viewDidLoad];
  40. self.presenter = [[LLAppPresenter alloc] initWithController:self];
  41. }
  42. @end

优点:

  • 每个Presenter对应着各自的ModelView
  • ModelView也更加的独立性、可复用
  • Controller里变得更简洁,只需要管理不同的Presenter就可以

MVVM

MVVM架构是以Model、ViewModel、View三者之间的关系来依赖的,其中的View包括了ViewController

ViewModel的作用是将Controller的业务逻辑抽取出来,并且把ModelView做一个绑定关系

-w693

我们将MVC的tableview的示例做了更改后,代码如下

  1. // LLNews
  2. @interface LLNews : NSObject
  3. @property (copy, nonatomic) NSString *title;
  4. @property (copy, nonatomic) NSString *content;
  5. @end
  6. @implementation LLNews
  7. @end
  8. // LLNewsViewModel
  9. @interface LLNewsViewModel : NSObject
  10. - (void)loadNewsData:(void (^)(NSArray *newsData))completion;
  11. @end
  12. @implementation LLNewsViewModel
  13. - (void)loadNewsData:(void (^)(NSArray *))completion
  14. {
  15. if (!completion) return;
  16. NSMutableArray *newsData = [NSMutableArray array];
  17. for (int i = 0; i < 20; i++) {
  18. // 发送网络请求、字典转模型
  19. LLNews *news = [[LLNews alloc] init];
  20. news.title = [NSString stringWithFormat:@"news-title-%d", i];
  21. news.content = [NSString stringWithFormat:@"news-content-%d", i];
  22. [newsData addObject:news];
  23. }
  24. completion(newsData);
  25. }
  26. @end
  27. // LLNewsViewController
  28. @interface LLNewsViewController ()
  29. @property (nonatomic, strong) LLNewsViewModel *newsVM;
  30. @property (nonatomic, assign) NSArray *newsData;
  31. @end
  32. @implementation LLNewsViewController
  33. - (void)viewDidLoad {
  34. [super viewDidLoad];
  35. self.newsVM = [[LLNewsViewModel alloc] init];
  36. [self.newsVM loadNewsData:^(NSArray *newsData) {
  37. self.newsData = newsData;
  38. }];
  39. }
  40. #pragma mark - Table view data source
  41. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  42. return self.newsData.count;
  43. }
  44. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  45. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NewsCell" forIndexPath:indexPath];
  46. LLNews *news = self.newsData[indexPath.row];
  47. cell.detailTextLabel.text = news.title;
  48. cell.textLabel.text = news.content;
  49. return cell;
  50. }
  51. #pragma mark - UITableViewDelegate
  52. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  53. {
  54. NSLog(@"1111");
  55. }
  56. @end

优点:Controller可以不用写逻辑代码,相对减轻负担,MVVM可以结合一些响应式框架来更简便使用

架构分层

一般我们经常会分为三层架构,分别是界面层、业务层、数据层

MVC、MVP、MVVM这几种架构都是建立于界面层来讨论的

架构分层的目的就是为了降低耦合性,易于维护和开发

设计模式

什么是设计模式

设计模式(Design Pattern)是一套被反复使用、代码设计经验的总结
使用设计模式的好处是:可重用代码、让代码更容易被他人理解、保证代码可靠性
一般与编程语言无关,是一套比较成熟的编程思想### 设计模式的几大类设计模式可以分为三大类- 创建型模式:对象实例化的模式,用于解耦对象的实例化过程 - 单例模式、工厂方法模式,等等- 结构型模式:把类或对象结合在一起形成一个更大的结构 - 代理模式、适配器模式、组合模式、装饰模式,等等- 行为型模式:类或对象之间如何交互,及划分责任和算法 - 观察者模式、命令模式、责任链模式,等等具体概述之后再详细讨论

原文链接:http://www.cnblogs.com/funkyRay/p/ios-di-ceng-yuan-li-shi-jia-gou-she-ji.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号