今天的电脑还是没有到呢,今天的学习还是只能从理论继续啦

不过再不到的话,还有两天我就要学完了,那可怎么办呀…

IOS文件管理

每一个只能访问自己沙盒中的文件资源
每一个Bundles的App都有一个自己的文件夹,下面有一个应用配置信息和二进制文件 & 资源
在程序开发时访问的是一个文件系统,存放在系统的Data文件夹,App下面有一些子文件夹
我们在开发的过程中可以存取到自己App下的子文件夹目录

沙盒机制

只能访问程序自己的目录,是每个App特有的文件夹
Documents 可以进行备份和恢复,体积较大,存放用户数据,支持用户共享
Library 开发者最常使用的文件夹,可以自定义子文件夹例如Cache Preferences(用户偏好设置,NSUserDefault,支持备份)Cache(不需要缓存的,体积较大,一般的删除缓存操作)
SystemData 系统数据
tmp 临时文件不会备份,启动会被清除

IOS获取沙盒地址

NSSearchPathForDirectoriesInDomains可以相应的取出文件地址
使用范例:
该函数返回的是一个数组,一般来说我们取第一个元素就代表了我们要找的目录
苹果提供了一部分常用的宏来快速访问一些常用的地址

NSFileManager

关注文件和文件夹层面的操作
创建、删除、查询、移动和复制等
通过NSURL或者NSString作为Path
  • createDirectoryAtPath
  • createFileAtPath
  • fileExistsAtPath
  • contentsOfDirectoryAtPath
  • contensAtPath
  • attributesOfItemsAtPath
  • removeItemAtPath
  • NSFileManagerDelegate提供移动、复制、删除等操作的具体自定义实现,完成一定操作过后会进行回调

NSFileHandle

更加细化功能,可以在指定位置写入,读入指定长度等
  • 读取文件 & 写文件
  • 读取指定的长度 & 在指定位置追加/截断
  • 截断 & 立即刷新
  • 常用于追加数据

取数据示例:

NSCoder

归档和解归档(序列化和反序列化)
提供简单的函数可以在Object和二进制数据间进行转换
抽象类具体功能需要子类实现
encode和decode都需要提供一个key进行一个标志,为了序列化向前向后兼容
  • 顺序存储 如果新插入了一个属性,在decode的时候就无法兼容
  • 使用属性名称做Key 在删除这个属性的时候也会出问题
  • 自定义Key 这样就不会存在问题了,我们可以在业务层逻辑保证这个事情

NSKeyedArchiver

NSCoder的子类
提供简单的函数,在Object和二进制数据间进行切换
提供基本的delegate
需要Object自己处理Key-Value对应关系,即需要遵循NSCoder协议
该协议包含两个函数
  • – (nullable instancetype)initWithCoder:(NSCoder *) aDecoder
  • – (void) encodeWithCoder:(NSCoder *)aCoder
NSArray和NSDictionary等类型系统以及实现协议
NSSecureCoding 解决文件替换攻击、序列化时规定class包含函数supportsSecureCoding
序列化和反序列化:

NSUserDefault

可以看成一个Key-Value类型的数据库,保存在/Library/performances下
  • 存储轻量级的数据
  • 一般用于用户的偏好设置
  • 支持基本数据类型
相比于之前的NSCoder这个是二进制流和Object转换上层的一层封装

开源存储框架对比

系统级存储

NSUserDefault / Keychain / CoreData / NSKeyedArchived

Key-Value类型

LevelDB / MMKV / Realm

关系数据库类型

SQLite / FMDB / WCDB

缓存数据

  • 对于列表数据可以通过NSKeyedArchiver保存列表数据
加载本地数据 -> 网络请求成功后替换
  • 使用NSUserDefault保存已读状态
已读过的新闻,列表显示不同颜色
  • 实际项目中的使用
结合项目架构,选择存储方式
数据库/KV/系统级
  • BOOL不建议存储在NSUserDefault中
网络和存储的结合
  • 优化占位体验
  • 使用缓存数据防止重复请求

IOS中多线程

IOS中的进程 & 线程

  • 一个App就是一个进程
  • IOS开发中较少用到进程间通信,一般都是线程通信

IOS中的主线程/非主线程

  • 保证流畅体验及线程安全,所有UI操作都集中到主线程
  • 影响UI体验(较长时间的操作)

IOS中多线程相关的知识点

  • NSThread / GCD / NSOperation / Runloop …

NSThread

是IOS中的线程,作为pthread的封装
创建新的线程、执行过后自动销毁、每次都要创建、手动进行线程同步、手动管理线程的生命周期
initWithTarget:selector:object:创建新的线程
@property (class, readonly, strong) BOOL isMainThread;
@property (class, readonly) NSThread *currentThread;
initWithBlock等

GCD(Grand Central Dispatch)

  • 高性能的多线程解决方案,自动利用CPU
  • 线程池模式,自动分配/调度线程,管理线程的生命周期
  • 通过队列管理多任务,FIFO
  • 对开发者使用队列代替线程的创建
  • 主线程对应主队列
  • 非主线程按照优先级分为4个队列High / Default / Low / Background
  • 自定义队列(dispatch_queue_serial、dispatch_queue_concurrent)
三个函数
  • dispatch_async(queue, block);异步执行,可以跳出运行块,先运行后面的部分
  • dispatch_sync(queue, block);同步执行
  • dispatch_after(when, queue, block);可以设定延迟时间等
注意:循环引用T_T

常用函数
  • dispatch_once 只运行一次
  • dispatch_source 事件源,自定义触发和监听
  • dispatch_group 多个互相引用的时候会使用这个
  • dispatch_semaphore 信号量线程间同步
  • dispatch_barrier_async 并发队列的同步点

NSOperation

由于GCD缺少可定制性和复杂的依赖
Block变成一个面向对象的封装,可以提供任务之间的依赖关系,支持取消暂停任务,优先级的设置,子类可以继承实现,队列支持最大并发数设置等

NSOperationQueue

对应了GCD中的队列

Runloop

主线程有Runloop,当空闲的时候会进入阻塞状态,伴随线程的任务处理循环
Runloop和线程一一对应
应用:
  • NSTimer
  • performselector

图片的下载和存储

从网络加载图片:
网络上读取
磁盘中读取(可以加速)
缓存中读取(最快)
使用异步的请求加载 & 缓存,尽量减少网络请求
多个请求的管理 / 优先级等
图片库需要拥有以下特点
  • 提供基本的下载管理
  • 提供基本的存储逻辑
  • 提供常用的编解码
  • 方便使用

SDWebImage

使用CocoaPod集成
sd_setImageWithURL
具有存储缓存方案,cacheType具有磁盘和缓存的二级存储关系
执行完了过后会有回调
其他开源框架
  • FastImageCache
  • LKImageKit

对于图片库的修改 & 二次封装

  • 特殊的编解码
  • 大量图片同时渲染
  • 本地图片的加载和使用
  • 特殊的裁剪
  • Cache策略 & 用户隔离

网络、存储、多线程模型

如果在缓存中找到需要的,就直接返回即可,如果没有,从网络下载并保存到缓存中

音视频框架

AVKit

封装了UIKit等UI组件,对应AVPlayerViewController,是一个较高级的接口,创建全部视图层服务、用户控制、导航等

AVFoundation

AVPlayer/AVAsset,基于时间的音视频框架
MVC结构划分
M:AVAsset,提供与格式无关的媒体数据
AVPlayerItem协调AVAsset和AVPlayer,Notification,AVPlayerItemStatus等
C:AVPlayer 开始 / 暂停,封装对播放资源的简单操作
V:AVPlayerLayer 播放器画面

实践

定义一个coverView和一个playButton,将所有的指定位置放置展位图和playButton的图片
定义一个外部接口加载视频的图片和_coverView和_playButton.image等
AVAsset加载videoURL,AVPlayerItem加载AVAsset,AVPlayer加载AVPlayerItem(其实也可以直接加载URL)以上两个类可以省略,但是给我们提供了重定义的一个接口
使用avPlayer生成一个playerLayer
playerLayer.frame = _coverView.bounds;
[_coverView.layer addSublayer:PlayerLayer];
最后[avPlayer play]即可
注意我们播放的时候,视频的页面要加载到整个View的最上面,挡住button
知识链接:__kindof修饰词,用于修饰函数返回值,当使用__kindof的时候,本类和子类都可以作为返回值返回

NSNotification

Delegate

只能一对一,可以有返回值,互相引用

KVO

监听的方式,一对多,只能作用在value和变化上,需要互相依赖,单方向无协同
forKeyPath:@”status”表示对属性监听,属性变化:NSKeyValueOb…OptionNew
dealloc时也需要移除Observer
上述视频播放中,AVPlayerItem可以直接addObserver监听的加载和播放状态
addObserver:forKeyPath:context:

Notification

一对多,以一种事件的方式进行传播,可以携带更多的信息,常用于系统级消息,无依赖,单方向无协同
中心化管理NSNotificationCenter,对象需要在center中注册,广播也是通过center广播,主要关注系统级事件例如:前后台切换,内存警告等
接受通知addObserver发送通知postNotification
在上述的视频播放中,我们可以监听AVPlayerItem的Status,如果开始play的时候我们在进行play
操作是向中心注册AVPlayerItemDidPlayToEndTimeNotification,并添加相应函数
当对象销毁的时候我们需要移除掉这个Observer(dealloc中重写即可)

AVPlayer播放进度

可以由CMTime CMTimeMakeduration和currentTime实现
添加一个监听,forKeyPath与下面的监听方法对应
在KVO监听方法中添加上对应的forKeyPath即可
value是帧timesacle是帧率相除即为时间
但是CMTimeGetSeconds函数可以直接返回时长
使用的时候先从AVVideoItem中获取CMTime然后再调用函数返回视频时长和缓冲时长
我们如果要获取播放的时长可以采用addPeriodicTimeObserverForInterval:queue:usingBlock:方法,每秒回调一次

播放进度调整

AVPlayer中的seekToTime:即可直接跳到播放的进度
分类: IOS实习

0 条评论

发表评论

邮箱地址不会被公开。 必填项已用*标注