这是我参与「第四届青训营 -iOS场」笔记创作活动的的第6篇笔记
存储
沙盒
- iOS文件系统,沙盒
- MyApp.app,该目录包含了应用程序本身的数据
- Documents,使用这个目录保存用户数据
- Libaray,保存配置文件和数据库文件,使用
NSUserDefaults
写的数据都会保存在Libaray/Preferences
目录下的一个plist文件- tmp,保存临时文件
// doucments
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
// libaray
NSString *libDir = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
// cache
NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
// tmp
NSString *tmpDir = NSTemporaryDirectory();
NSLog(@"%@\n%@\n%@\n%@", docDir, libDir, cacheDir, tmpDir);
Bundle
- 本质上是App安装包,包括App资源
- Info.plist,版本信息、权限信息
- Executable,可执行文件
- Resource files,资源文件
- Other support files,动态库
- 生成,编译时会生成目标文件,链接静态文件,形成可执行文件;在运行时,链接动态库,进行运行时解析
NSString *path = [[NSBundle mainBundle] pathForResource:@"XXX" ofType:""];
序列化
- 字符串写入文件
[name writeToFile:path atomically:YES encoding:NSUnicodeStringEncoding error:nil];
- NSData读出
// NSDataReadingUncached:指示文件不应存储在文件系统缓存中的提示,只读取一次数据. (对于一次读取和丢弃的数据,此选项可以提高性能.)
// NSDataReadingMappedIfSafe:在不丢失的数据的情况下,文件应该映射到虚拟内存的,
// NSDataReadingMappedAlways:尽可能将文件映射到虚拟内存
[NSData dataWithContentsOfFile:path options:<#(NSDataReadingOptions)#> error:nil];
- 序列化与反序列化
- 序列化,将对象转换为字节序列
- 反序列化,将字节序列恢复为对象
- 为什么需要序列化,只能传输二进制的数据,把kv概念,转换成二进制
- 序列化协议,xml/json/protobuf
- NSJSONSerialization
// 序列化
[NSJSONSerialization dataWithJSONObject:<#(nonnull id)#> options:<#(NSJSONWritingOptions)#> error:<#(NSError *__autoreleasing _Nullable * _Nullable)#>]
// 反序列化
[NSJSONSerialization JSONObjectWithData:<#(nonnull NSData *)#> options:<#(NSJSONReadingOptions)#> error:<#(NSError *__autoreleasing _Nullable * _Nullable)#>]
其他存储
网络
- 网络
- 网络库
- NSURLSession原生
- NetWork.framework
- TTNewworkManager 字节跳动开源
- NSURL
- 统一资源定位符,解析URL字符串的各个部分的对象
- 文本路径也可以作为URL,有相应的初始化方法
- NSURLRequest
- 请求
- NSURLSession,整个请求的流程
- NSURLSessionConfiguration,对NSURLSession初始化进行配置,设置请求的cookie、密钥、缓存、请求头等参数
- NSURLSessionTask,负责执行具体请求的task,由session创建
- NSURLSessionTaskDelegate,不同任务的关键阶段定义的代理方法
多媒体技术
相册权限
- 通过Info.plist设置资源权限申请
- 需要导入
Phohos.framework/PhotosUI.framework
PHPickerConfiguration *config = [[PHPickerConfiguration alloc] init];
// 选择限制
config.selectionLimit = 3;
// 过滤器,过滤出图片
config.filter = [PHPickerFilter imagesFilter];
PHPickerViewController *pickerViewController = [[PHPickerViewController alloc] initWithConfiguration:config];
pickerViewController.delegate = self;
[self presentViewController:pickerViewController animated:YES completion:nil];
- 权限区别
视频播放
- AVPlay视频播放
NSURL *url = [NSURL fileURLWithPath:path];
AVPlayer *play = [AVPlayer playerWithURL:url];
[play play];
- 音效配置
是否引起不支持的混音的App中断,两个App的声音冲突时,另一个App是否会被中断
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
- 画中画,需要导入
AVKit.framework
AVPictureInPictureController *pc = [[AVPictureInPictureController alloc] initWithPlayerLayer:player];
滤镜
- 框架
- OpenGL状态机,一台保存状态,并根据当前状态进行相应输出的机器;进行特殊状态时,不再接收输入,ring值工作
- 非常庞大,首先要创建一个OpenGL的上下文
- 面向过程,可以封装为面向对象
- 切换上文开销大,可创建多个上下文独立使用,不同线程使用不同的上下文,可共享纹理、缓冲区
- 渲染管线,流水线渲染,其中
顶点着色器和片元着色器可编程
- 顶点着色器,顶点元素由CPU传个GPU
- 图元装配,组装成形状
- 栅格化,将图元转换为像素
- 片元着色器,给像素赋予真正的颜色
- 测试与混合,判断这个像素在前还是在后,调整透明度和深浅
设计模式
类蔟
NSNumber
是抽象工厂模式的实践,管理隐藏在公共抽象父类下的具体私有子类,Number作为抽象工厂类,数据类型作为具体的实现
- 优点,隐藏实现细节;简化开发成本;便于增加实际类型;减少if-else
- 缺点,抽象工厂增加方法,所有子类都需要进行必要的实现,已有的类蔟不好扩展
观察者模式的应用
NSNotificationCenter
,内部维护三个数据结构,有主题和Object的Map/没主题有Object的Map/没主题没Object的链表,收到对应的通知后,在对应的数据结构中进行匹配调用观察者的方法KVO
,当进行KVO时,创建了新的子类(继承原先的子类),原先实例对象的isa指针指向新的子类;新子类的内部setter方法被重写,调用KVO对应的方法- 优点
- 表示层和数据层逻辑分离
- 广播通信,简化一对多系统设计
- 满足开闭原则
- 缺点
- 容易产生循环依赖,互相监听
- 广播作用域没有权限限制
开发范式
- 本质
- 数据管理
- 数据加工
- 数据展示
- 解决的核心问题
- 支撑业务
- 控制复杂度,便于阅读代码,理解业务
- 提升研发效率
- 胖瘦Model
- 瘦,追求细粒度的Model,只提供基本属性
- 胖,根据业务要求,返回适合的属性格式,包含弱业务逻辑,复用性不强
- 发展
MVC
- 结构
- Model,数据
- Controller,监听View的交互事件
- View,界面
- model和view不应该感知对方的存在,便于复用
- controller可以对model和view进行调用和处理
- view和controller之间的通信方式,addTarget、代理、数据源
- 设计模式
- 组合模式,model和view组合在controller中
- 命令者模式,controller通过target决定如何响应view的行为
- 观察者模式,kvo
- 策略模式,不同响应方式
- 中介者模式,controller作为媒介
- 问题
- Controller臃肿,包括很多实际的View和事件处理
- Model太过于轻量级,大多数只是属性的映射
- 遗失的网络请求,与API通信的代码,没有专属的层次
- 较差的可测试性,Controller耦合Model和View
MVCS
- 瘦Model只用于表达数据
- 存储/处理交给Store层
- 拆分Controller关于数据处理的部分
MVVM
- 其中的View实际上是Controller+View
- ViewModel
- 视图层数据的提供者,对Model层的数据进行包装
- 视图层交互的响应者,进行view的业务逻辑的处理
- 在MVC基础上把Controller拆分出一部分,专门处理view和数据的业务逻辑
- Rx提供了很好的数据绑定方法,利于实现MVVM
VIPER
- View 视图显示
- Interactor 业务逻辑
- Presenter 交互
- Entity 实例数据
- Router 路由
MVX
- 理想架构
- 单向数据流
- 层与层界限清晰
- 特点
- 拆分细粒度高
- 层级解耦
- 各部分复用性高
- 易用性、可观测性