谈谈MVVM和链式网络请求架构

简介:

前言

前一段时间一直在学习iOS的架构。为什么呢?

公司的架构一直是MVC,当我们正式上线的时候,项目已经有了超十万行代码。主要的VC一般都有2000行代码以上。

关键是,目前版本我们只做了三分之一的业务逻辑…

所以,架构重构吧。

正文

MVVM

MVVM: Model-View-ViewModel

MVVM其实是MVC的进化版,它将业务逻辑从VC中解耦到ViewModel,来实现VC大’瘦身’。

用代码解释吧!

做一个简单的登录判断:

创建LoginViewModel(逻辑处理),LoginModel(只放数据),LoginViewController。

这里不用LoginView是为了让初学者能更好的把精力集中在用ViewModel解耦上。

当然要是你这些都明白,你可以直接看Wzxhaha/RandomerFramework,这是我在做的独立项目Randomer的基本架构(SubClasses+Protocol+MVVM+RAC)以及它的登录注册模块。另外,感谢王隆帅的这篇文章为我打开了新世界的大门。

在LoginModel中加入方法

 
 
  1. //.h 
  2.  
  3. - (instancetype)initWithUserName:(NSString *)username password:(NSString *)password
  4.  
  5.   
  6.  
  7. @property (nonatomic,copy,readonly)NSString * username; 
  8.  
  9. @property (nonatomic,copy,readonly)NSString * password
  10.  
  11.  
  12. //.m 
  13.  
  14. - (instancetype)initWithUserName:(NSString *)username password:(NSString *)password { 
  15.  
  16.     if (self = [super init]) { 
  17.  
  18.         _username = username; 
  19.  
  20.         _password = password
  21.  
  22.     } 
  23.  
  24.     return self; 
  25.  
  26.  

这个没什么好讲的,就是给Model加一个初始化方法。

在LoginViewModel中加入方法

 
 
  1. #import "PersonModel.h" 
  2.  
  3.   
  4.  
  5. - (instancetype)initWithPerson:(PersonModel *)person; 
  6.  
  7. @property (nonatomic,assign,readonly)BOOL canLogin; 
  8.  
  9.  
  10. - (instancetype)initWithPerson:(PersonModel *)person { 
  11.  
  12.     if (self = [super init]) { 
  13.  
  14.      //在这做你绑定model后的处理 
  15.  
  16.       _canLogin = [self valiCanLoginWithUserName:person.username password:person.password]; 
  17.  
  18.     } 
  19.  
  20.     return self; 
  21.  
  22.  
  23.   
  24.  
  25. - (BOOL)valiCanLoginWithUserName:(NSString *)username password:(NSString *)password { 
  26.  
  27.     if (username.length & password.length) { 
  28.  
  29.         return YES; 
  30.  
  31.     } else { 
  32.  
  33.         return NO
  34.  
  35.     } 
  36.  
  37.  

给ViewModel添加个绑定Model的初始化方法,以及判断帐号密码是否有效的方法。

然后VC(或者View)就可以直接这样获得判断后的结果

 
 
  1. PersonModel * person = [[PersonModel alloc]initWithUserName:@"10" password:@"10"]; 
  2.  
  3. PersonViewModel * viewModel = [[PersonViewModel alloc]initWithPerson:person]; 
  4.  
  5.   
  6.  
  7. NSLog(@"%d",viewModel.canLogin);  

简单的功能的时候没什么,当你处理复杂的逻辑判断的时候,MVVM会有巨大优势。

顺便讲一下ReactiveCocoa,我之所以这么推崇MVVM,主要就是因为RAC和MVVM简直太配了!

ReactiveCocoa

RAC具有函数式编程和响应式编程的特性,要是对编程思想不熟的可以看我的WZXProgrammingIdeas

RAC最大的用处就是能监听到各个事件,RAC把这个叫做信号流,然后接受信号通过block回调,里面大量的使用了block,所以一定要用好@weakify(self)和@strongify(self)。

为什么说RAC和MVVM太配了?

MVVM是把方法解耦到ViewModel,但是还是要VC(V)调用的,那么判断什么时候调用的逻辑还是会复杂。

而RAC解决了这个问题,它负责监听事件,然后调用ViewModel来进行逻辑判断。

例如:

 
 
  1. [[_registerBtn rac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(id x) { 
  2.  
  3.       @strongify(self) 
  4.  
  5.       [self.viewModel toRegisterWithType:Register]; 
  6.  
  7.   }]; 
  8.  
  9.  
  10.  
  11.   [[_loginBtn rac_signalForControlEvents:UIControlEventTouchUpInside]subscribeNext:^(id x) { 
  12.  
  13.       @strongify(self) 
  14.  
  15.       [self.viewModel loginWithUserName:self.usernameTextField.text password:self.usernameTextField.text Success:^(idresponse) { 
  16.  
  17.       } failure:^{ 
  18.  
  19.           SHOW_ERROR(@"错误", @"账号或密码错误"
  20.  
  21.       } error:^(NSError *error) { 
  22.  
  23.           SHOW_ERROR(@"错误", @"网络连接失败"
  24.  
  25.       }]; 
  26.  
  27.   }];  

RAC监听了登录和注册按钮,使得代码简洁,而且结构十分紧凑。

Demo的话还是看这个吧Wzxhaha/RandomerFramework

https://github.com/Wzxhaha/RandomerFramework

或者简单版的WZXRACDemo

https://github.com/Wzxhaha/WZXRACDemo

链式网络请求框架

为什么封装WZXNetworking

这是一个容错性非常吓人的框架。

 
 
  1. [[WZXNetworkManagermanager].setRequest(@"http://192.168.1.40:8001").RequestType(POST).HTTPHeader(nil).Parameters(nil).RequestSerialize(RequestSerializerHTTP).ResponseSerialize(ResponseSerializerJSON) startRequestWithSuccess:^(id response) { 
  2.  
  3.   
  4.  
  5.         NSLog(@"success"); 
  6.  
  7.     } failure:^{ 
  8.  
  9.   
  10.  
  11.         NSLog(@"failure"); 
  12.  
  13.     }]; 

在这里除了.setRequest(url)和startRequestWithSuccess failure方法,其他都是非必要的。

你可以这样:

 
 
  1. [[WZXNetworkManager manager].setRequest(@"http://192.168.1.40:8001") startRequestWithSuccess:^(id response) { 
  2.  
  3.   
  4.  
  5.         NSLog(@"success"); 
  6.  
  7.     } failure:^{ 
  8.  
  9.   
  10.  
  11.         NSLog(@"failure"); 
  12.  
  13.     }];  

链式在参数和参数的选择很多的情况或者很有可能改动的情况下展现了惊人的优势。因为,它的改动十分方便,只不过添加或者修改一个方法。

打个比方:

换成集中式API封装应该是这样的:

 
 
  1. - (void)GET:(NSString *)url 
  2.  
  3.         parameters:(id)Parameters 
  4.  
  5.         success:(SuccessBlock)success 
  6.  
  7.         failure:(FailureBlock)failure; 

当你要添加一个Version属性做API版本判断的时候,你能怎么办?只能重写方法,在方法中加入一个Version参数,然后所有使用的网络请求都要改变方法。

换成分布式API封装我们则不考虑对比了..

 
 
  1. GeneralAPI *apiGeGet            = [[GeneralAPI alloc] initWithRequestMethod:@"get"]; 
  2.  
  3. apiGeGet.apiRequestMethodType      = RequestMethodTypeGET; 
  4.  
  5. apiGeGet.apiRequestSerializerType  = RequestSerializerTypeHTTP; 
  6.  
  7. apiGeGet.apiResponseSerializerType = ResponseSerializerTypeHTTP; 
  8.  
  9. [apiGeGet setApiCompletionHandler:^(id responseObject, NSError * error) { 
  10.  
  11.     NSLog(@"responseObject is %@", responseObject); 
  12.  
  13.     if (error) { 
  14.  
  15.         NSLog(@"Error is %@", error.localizedDescription); 
  16.  
  17.     } 
  18.  
  19. }]; 
  20.  
  21. [apiGeGet start];  

这样的结构是否太松散?

再换成WZXNetworking

我们要做的只是再添加一个方法和一个成员变量,然后在原有方法后面加一个.method()

 
 
  1. - (WZXNetworkManager * (^) (id some))method { 
  2.  
  3.   return ^WZXNetworkManager (id some) { 
  4.  
  5.      self.XXX = some 
  6.  
  7.      return self; 
  8.  
  9.   } 
  10.  
  11.  
 
 
  1. [[WZXNetworkManager manager].setRequest(@"http://192.168.1.40:8001").method(some) startRequestWithSuccess:^(idresponse) { 
  2.  
  3.   
  4.  
  5.         NSLog(@"success"); 
  6.  
  7.     } failure:^{ 
  8.  
  9.   
  10.  
  11.         NSLog(@"failure"); 
  12.  
  13.     }];  







本文作者:佚名
来源:51CTO
目录
相关文章
|
1月前
|
负载均衡 安全 API
SDN网络架构分为哪三层
SDN软件定义网络是一种创新的网络架构,旨在提供更灵活、可编程和智能的网络管理。SDN的设计理念是通过将网络控制平面和数据平面分离,实现对网络行为的集中控制和编程。
|
1月前
|
消息中间件 存储 缓存
Kafka【基础知识 01】消息队列介绍+Kafka架构及核心概念(图片来源于网络)
【2月更文挑战第20天】Kafka【基础知识 01】消息队列介绍+Kafka架构及核心概念(图片来源于网络)
94 2
|
2月前
|
机器学习/深度学习 测试技术 Ruby
YOLOv5改进 | 主干篇 | 反向残差块网络EMO一种轻量级的CNN架构(附完整代码 + 修改教程)
YOLOv5改进 | 主干篇 | 反向残差块网络EMO一种轻量级的CNN架构(附完整代码 + 修改教程)
130 2
|
3天前
|
人工智能 安全 大数据
SDN(软件定义网络)——重塑网络架构的新视角
SDN(软件定义网络)是网络架构革新的关键,通过分离控制与数据平面,实现网络的灵活、高效管理。未来,SDN将更广泛应用于各行业,与云计算、大数据、AI融合,推动数字化转型。开放与标准化的趋势将促进SDN生态发展,提供以业务需求为导向、智能化自动化管理及增强网络安全的新视角。SDN将在更多领域扮演重要角色,支持网络技术的创新与进步。
|
5天前
|
网络架构
经典神经网络架构参考 v1.0(2)
经典神经网络架构参考 v1.0
11 0
|
26天前
|
移动开发 前端开发 数据管理
构建高效Android应用:采用MVVM架构与LiveData的全面指南
在移动开发领域,构建一个既快速又可靠的应用对于开发者来说至关重要。随着Android Jetpack组件的推出,MVVM(Model-View-ViewModel)架构和LiveData已成为实现响应式、可测试且易于维护应用的首选解决方案。本文将深入探讨如何在Android应用中实施MVVM模式,以及如何利用LiveData来优化UI组件的数据更新流程,确保用户界面与业务逻辑之间的高度解耦和流畅交互。
18 4
|
1月前
|
Cloud Native 安全 网络安全
构建未来:云原生架构在企业数字化转型中的关键角色网络安全与信息安全:防御前线的关键技术
【2月更文挑战第30天】 随着数字转型的浪潮席卷各行各业,企业正寻求更加灵活、可扩展的解决方案以适应不断变化的市场需求。本文将深入探讨云原生架构如何成为支持这一转型的核心技术,分析其优势和挑战,并提出实施策略。云原生技术的采用不仅加速了开发过程,还提供了自动化运维、弹性伸缩等特性,为企业带来了前所未有的敏捷性和效率。然而,迁移至云原生架构也伴随着技术复杂性增加和安全风险的挑战。文章最后,我们将提供一系列最佳实践,帮助企业在采纳云原生技术的过程中规避风险,实现持续创新。 【2月更文挑战第30天】 在数字化时代,数据成为核心资产,而网络安全与信息安全则是维护这些资产不可或缺的屏障。本文深入探讨了
|
1月前
|
移动开发 前端开发 C#
MVVM风格架构
MVVM风格架构
28 2
|
2月前
|
前端开发 JavaScript API