iOS 架构杂谈
2020-10-28 本文已影响0人
望穿秋水小作坊
一. 开篇
1. 一句话概括客户端其实大部分都在干些什么事情?
--------------- --------------- --------------- ---------------
| | | | | | | |
| 调用网络API | --> | 展现列表 | --> | 选择列表 | --> | 展现单页 |
| | | | | | | |
--------------- --------------- --------------- ---------------
^ |
| |
| |
------------------------------------------------------------
- 简单来说就是调用 API,展示页面,然后跳转到别的地方再调用 API,再展示页面。
2. APP确实主要做这些事情,但是支持这些事情的基础,就是做架构要考虑的事情。(举三个)
- 调用网络 API
- 页面展示
- 数据的本地持久化
3. 详细一点说明架构在上面三件事情的作用?
-
如何让业务开发工程师
方便安全
地调用网络 API?然后尽可能保证用户
在各种网络环境下都能有良好的体验? -
页面如何组织,才能尽可能降低业务方代码的
耦合度
?尽可能降低业务方开发页面的复杂度
,提高他们的效率
? -
当数据有在
本地存取的需求
的时候,如何能够保证数据在本地的合理安排
?如何尽可能地减少性能消耗
?
4. 架构设计的方法
- 第一步:搞清楚要解决哪些问题,并找到解决这些问题的充要条件
- 第二步:问题分类,分模块
- 第三步:搞清楚各个问题直接的依赖关系,建立好模块交流规范并设计模块
- 第四部:推演预测一下未来可能的走向,必要时添加新的模块,记录更多基础数据以备未来之需
- 第五步:先解决依赖关系中最基础的问题,实现基础模块,然后再用基础模块堆叠出整个架构
- 第六步:打点,跑单元测试,跑性能测试,根据数据去优化对应的地方
5. 什么样的架构叫好架构?
- 代码整齐,分类明确,没有 common,没有 core
- 不用文档,或很少文档,就能让业务方上手
- 思路和方法要统一,尽量不要多元
- 没有横向依赖,万不得已不出现跨层访问
- 对业务方该限制的地方有限制,该灵活的地方要给业务方创造灵活实现的条件
- 易测试,易拓展
- 保持一定量的超前性
- 接口少,接口参数少
- 高性能
6. 我们常说的三层架构或四层架构通常指的是什么?
- 三层架构:展现层、业务层、数据层
- 四层架构:展现层,业务层、网络层、本地数据层
7. 为什么流行起来的是三层架构
,而不是四层架构
或者五层架构
?
- 因为所有的模块角色只会有三种:
数据管理者、数据加工者、数据展示者
。 - 笼统来说,软件只会有三层,每层扮演一个角色。
- 其他的第四层第五层,一般都是这三层里面的其中之一分出来的,最后都能归纳进这三层的某一层中区,所以用
三层架构
来描述就比较普遍。
8. 三层架构
和 MVC
之间是什么关系?
-
MVC
通常只是针对 三层架构中的展现层
做的架构 - 三层架构描述的侧重点是
模块之间
的逻辑关系
- MVC描述的侧重点在于
数据流动方向
二. view 层的架构
1. 为什么说 view 层架构是最重要的?
- View 层架构是最影响业务方迭代周期的因素之一
- View 层架构是最贴近业务的底层架构
2. ViewController
代码结构的规定
- 首先我们应该遵循苹果的代码设计规范 https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html
- 然后约定
ViewController
中的代码:先是lifecycle
,然后是Delegate 方法实现
,然后是event response
,接着是private method
,最后才是getters and setters
-
viewDidLoad
里面只做addSubview
的事情,然后layoutPageSubviews
里面做布局的事情,最后在viewDidAppear
里面做Notification
的监听之类的事情。至于属性的初始化,则交给getter
去做。
@interface CustomObject()
@property (nonatomic, strong) UILabel *label;
@end
@implement
#pragma mark - life cycle
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view addSubview:self.label];
[self layoutPageSubviews];
}
- (void)layoutPageSubviews {
[self.label addConstraints:xxxConstraints];
}
#pragma mark - getters and setters
- (UILabel *)label
{
if (_label == nil) {
_label = [[UILabel alloc] init];
_label.text = @"1234";
_label.font = [UIFont systemFontOfSize:12];
... ...
}
return _label;
}
@end
3. 在 10 以上的团队中,使用 nib
和 代码写 View
哪种更优?
具有一定规模的团队化 iOS 开发(10 人以上)有以下几个特点:
- 同一份代码文件的作者会有很多,不同作者同时修改一份代码的情况也不少见。因此,用 Git 进行代码版本管理时出现
Conflict
的几率也比较大。- 需要变换非常频繁,产品经理一时一个主意,为了完成需求二针对现有代码进行微调的情况,以及针对现有代码的
部分复用
的情况也比较多。- 复杂界面元素、复杂动画场景的开发任务比较多。
综上所述:实现简单的东西,用Code一样简单,实现复杂的东西,Code比StoryBoard更简单。所以我更加提倡用code去画view而不是storyboard。
4. View 的布局采用什么方案?
- 推荐采用
Masonry
方案,可读性强,可自动适配 -
CGRectMake
的话可读性很差,光看那几个数字,也无法知道 view 和 view 之间的位置关系。 - 用原生
Autolayout
可读性稍微好点,但是生成的constraint
的长度实在太差,代码观感不好
5. 是否有必要让业务方统一派生 ViewController?
// todo
6. 关于 MVC,请描述 Model,View,Controller 各做什么事情?
M 应该做的事情:
- 给 ViewController 提供数据
- 提供 ViewController 存储数据提供接口
C 应该做的事情:
- 管理 View Container 的生命周期
- 负责生成所有 View 的实例,并放入 View Container
- 监听来自 View 与业务有关的事情,通过与 Model 的合作,来完成对应事件的业务。
V 应该做的事情:
- 响应与业务无关的事件,如因此引发动画效果,点击反馈效果等。
- 界面元素表达
二. 网络层的架构
1. 如何确保 API 的调用者是来自你自己的 APP,防止竞争对手爬你的 API?
- 服务端和客户端拿着
同一个密钥
。客户端发起请求时,将API 名字和请求参数
用密钥
摘要出一个hash1 值
,请求时带上这个hash 值
。 服务端拿到数据,用同一个密钥进行摘要出一个hash2 值
。如果hash1
和hash2
相同就证明是来你自己的 APP。 - 客户端保存这个密钥的时候,尽量不要存储到本地,直接写入代码中,被逆向的难度会大很多。
2. 如何防止中间人攻击,比如运营商很喜欢往用户的 HTTP 请求里面塞广告?
- 使用 https
3. 网络层的优化方案(针对链接建立环节的优化)?
网络层的优化方案三. 本地数据持久化层的架构
1. NSUserDefault
- 一般来说,存放小规模数据,弱业务相关数据
- 本质上就是类似 plist 的存储方式
2. keychain
- Keychain 是苹果提供的带有可逆加密的存储机制,普遍用在各种存密码的需求上。
- 另外,由于 APP 卸载只要系统不重装,Keychain 中的数据依旧能够得到保留,以及可被 iCloud 同步的特性,大家都会在这里存储用户的唯一标识。
3. 文件存储
- 包括 Plist、archive、Stream 等方式
- 一般结构化的数据或需要方便查询的数据,都会以 Plist 的方式去持久化
- Archive 适合存储对象化的数据,Decode 比较花时间
- Stream 就是一般文件存储,一般用于存存图片之类的,适合比较经常使用的
4. 数据库存储
- 使用数据库最重要的目的就是 CRUD(增删改查)
- 比较常见的是 FMDB