2021-06-19

UI试图相关问题

大纲

  • UITableView 相关
  • 事件传递&视图响应
  • 图像显示原理
  • 卡顿&掉帧
  • 异步绘制&绘制原理
  • 离屏渲染

重点:

1、重用机制
2、并发访问,更新数据(1、子线程同步主线程的操作2、多线程操作同步到串行队列执行)
3、传递和响应(传递由上到下,响应由下往上)
4、图像显示原理

  • CPU 处理布局,绘制,图像编解码,提交位图
  • GPU 渲染管线(顶点着色,图元装配,光栅化,片段着色,片段处理)

5、处理UI卡顿掉帧的问题

  • 原因 VSync信号来临时,GPU中不能提交相应画面数据(未处理完)

6、异步绘制 实现了layer的delegate方法,即可进行异步绘制displayLayer

Object-C特性

大纲

  • 分类
  • 关联对象
  • 扩展
  • 代理
  • 通知
  • KVO
  • KVC
  • 属性关键字

重点

分类:

  • 运行时决议
  • 可以为系统类添加分类
  • 添加 1、实例方法 2、 类方法 3、协议 4、属性
  • 最后编译的分类方法优先生效
  • 分类添加的方法“覆盖”原类方法
  • 名字相同的分类会引起编译报错

关联兑现:

  • 为分类所添加的成员变量不会被添加到宿主类上,而是关联到AssocitationsManager管理(HashMap)

扩展:

  • 用扩展生命私有属性
  • 用扩展生命私有方法
  • 用扩展生命私有成员变量
  • 编译时决议
  • 只以声明的形式存在
  • 不能为系统类添加扩展

代理

  • 软件设计模式
  • @protocol
  • 一对一

通知:

  • 一对多
  • 使用观察者模式实现,用于跨层传递消息的机制

KVO

  • 观察者模式的一种实现
  • isa混写技术来实现KVO(修改监听对象的isA指针的指向)
  • 手写KVO valueWillChanged、valueDidChanged

KVC

  • key value coding
  • 先判断有没有属性方法,如果没有,则判断有无实例变量,如也没有则报错

属性关键字

  • atomic
  • nonatomic
  • assign/week
  • copy

Runtime

大纲

  • 数据结构
  • 类对象与原类对象
  • 消息传递
  • 方法缓存
  • 消息转发
  • Method-Swizzling
  • 动态添加方法
  • 动态方法解析

数据结构

  • objc_object
    结构体: isa_t、关于isa操作相关、弱引用相关、关联对象相关、内存管理相关
  • objc_class
    结构体:suoerClass指针、cache_t cache(方法缓存)、class_data_bits_t(只读信息,协议,属性,方法)
  • method_t
    名称,返回值,参数,函数体
    const char* types => Type Encodings
    返回值 参数1 参数2 ... 参数n
    只读信息中:name 原生方法列表 成员变量 属性 协议
  • 对象、类对象、原类对象(关系)

消息传递

void objc_mgsSend(Void /* id self, SEL op, .../)
void objc_mgsSendSuper(Void /
struct objc_super super, SEL op, .../)

消息转发流程

resolveInstanceMethod: 返回YES 消息处理结束 ,返回NO forwardingargetForSelector: 返回转发目标, 返回nil methodSignatureForSelector: 返回方法签名,返回nil 报错

Method-Swizzling

  • 方法交换

动态添加方法

  • class_addMethod: 接受对象,函数名,方法签名

动态方法解析

  • @dynamic

内存管理

大纲

  • 内存布局
  • 内存管理方案
  • 数据结构
  • ARC & MRC
  • 引用计数
  • 弱引用
  • 自动释放池
  • 循环引用

内存布局

  • 栈(向下增大)
  • 堆(向上增大)
  • 未初始化数据
  • 已初始化数据
  • 代码段

内存管理方案
iOS是怎样管理内存的?

  • TaggedPointer
  • NONPOINTER_ISA (非指针型isa)
  • 散列表(弱引用表和引用计数表)

NONPOINTER_ISA
散列表

  • SideTavles() 结构 ,是一个哈希表,是一个多张表,可以实现分离锁

怎样实现快速分流
使用hash表查找,提高查找效率

数据结构
散列表的数据结构

  • Spinlock_t 自旋锁
  • RefcountMap 引用计数表
  • weak_table_t 弱引用表

Spinlock_t

  • 是一个“忙等”的锁。
  • 适用于轻量访问

RefcountMap

  • 是一个hashMap
  • 使用hash查找为了提高引用效率

weak_table_t

  • 是一个hashMap
  • 存储了弱引用对象的指针

MRC

手动引用计数

  • alloc 分配内存空间
  • retain 引用计数加一
  • release 引用计数减一
  • retainCount 获取对象的引用计数
  • autorelease 在autoreleasePool结束的时候调用release
  • dealloc 调用super dealloc

ARC

自动引用

  • ARC是LLVM和Runtime协作的结果
  • ARC新增了weak、strong属性关键字

引用计数管理

alloc实现

调用了c函数的calloc
此时并没有增加retainCount为1

retain

  • 查找对象的SideTable表
  • 从SideTable表中获取当前对象的引用计数值
  • 对引用计数值进行+1操作

release

  • 查找SideTable
  • 从SideTable表中获取当前对象的引用计数值
  • 对引用计数值进行-1操作

retainCount

  • 查找SideTable
  • 从SideTable表中获取当前对象的引用计数值
  • 若不存在引用计数,则对引用计数值进行+1操作

dealloc
当前对象是否可以直接释放一句以下判断条件

  • nonpointer_isa
  • weakly_referenced
  • has_assoc 是否有关联对象
  • has_cxx_dtor 是否有C++内容,或是否使用arc管理内存
  • has_sidetable_rc 当前对象的引用计数是否通过sidetable表维护的

以上全部为否才可以调用C函数直接释放
否则就要调用object_dispose() 进行释放

object_dispose

  • 开始
  • objc_destructInstance(): c++释放、移除关联对象、将弱引用指针置位nil、清除引用计数
  • c函数free()
  • 结束

弱引用管理
添加弱引用变量的流程

  • objc_initWeak()
  • storeWeak()
  • weak_register_no_lock()
    1 通过对象指针hash计算查找
    2 如果已经存在了弱引用数组,则添加
    3 如果没有,则创建弱引用数组

清除weak变量,同事设置为nil

  • dealloc
  • 。。。
  • weak_clear_no_lock()

自动释放池

  • runloop将要结束时调用pop操作
  • 多层嵌套就是多次插入哨兵对象
  • 在for循环中alloc创建了较大的内存消耗是,可手动插入autoReleasePool来释放内存对象

循环引用

  • 自循环引用
  • 相互循环应用
  • 多循环引用

考点

  • 代理
  • Block
  • NSTimer
  • 大环引用

如何破除

  • 避免产生
  • 在合适的时机手动破除循环引用

__weak
__block(ARC下会被强引用)
__unsafe_unretained 修饰对象不会增加引用计数,但是会产生悬垂指针

解决NSTimer的循环引用问题
NSTimer会被Runloop引用,所以必须手动释放NSTimer来解除引用。
采用中间对象,同时弱引用NSTimer和对象,当对象被释放后,NSTimer回调后,判断弱引用对象已经释放为nil,此时则invalidate timer,将NSTimer置位nil,此时NSTimer也被成功释放。

Block

大纲

  • Blokc介绍
  • 截获变量
  • __block修饰符
  • Block的内存管理
  • Block的循环引用

Block = 函数 + 上下文 + 对象
Block截获变量

Block

  • 全局类型block _NSConcreteGlobalBlock (堆)
  • 栈类型block _NSConcreteStackBlock (栈)
  • 堆类型block _NSConcreteMallocBlock (已初始化数据区)

栈:拷贝 -》 堆:拷贝-》 堆(引用计数器+1)

注意:
使用了__block 修饰的的截获变量修改,会对block进行copy

多线程

大纲

  • GCD
  • NSOperation
  • NSThread
  • 多线程与锁

GCD

  • 同步/异步 和 串行/并发
  • dispatch_barrier_aysnc
  • dispatch_group
  1. 同步/异步 和 串行/并发
    1.1 dispatch_sync(serial_queue /串行队列/,, ^{ // 任务 });
    1.2 dispatch_async(serial_queue, ^{ // 任务 });
    1.3 dispatch_sync(concurrent_queue /并发队列/, ^{ // 任务 });
    1.4 dispatch_async(concurrent_queue, ^{ // 任务 });

  2. dispatch_barrier_async
    2.1 如何实现多读单写
    dispatch_barrier_async(concurrent_queue, ^{ // 写操作 });

  3. dispatch_group
    3.1 A,B,C三个任务完成后,再执行D

NSOperation

  1. NSOperationQueue
    1.1 可以添加任务依赖
    1.2 可以添加任务执行状态
    1.3 可以控制最大并发量

任务执行状态

  • isReady
  • isExcuting
  • isFinished
  • isCancelled

状态控制

  1. 只重写main时,则无法控制状态
  2. 重写了start,自行控制任务状态

通过KVO来监听NSOperation状态

NSThread

  • 如何实现常驻线程
  • Start方法内部实现机制(开启线程,执行函数,关闭线程)

多线程和锁

  • NSRecursiveLock
  • NSLock
  • dispatch_semaphore_t
@synchronized

单例对象

atomic

原子性赋值

OSSpinLock

自旋锁(循环等待访问,不释放当前资源)

NSLock
NSRecursiveLock

递归锁,可以重注

dispatch_semaphore_t

信号量

RunLoop

大纲

  • 概念
  • 数据结构
  • 事件循环机制
  • RunLoop与NSTimer
  • RunLoop与多线程

什么是RunLoop

RunLoop是通过内部维护的事件循环来对事件/消息进行管理的一个对象

  • 维护事件循环
  • 处理事件和消息的
  • 对象
  1. 事件循环
  • 没有消息处理时,休眠以避免资源占用
  • 有消息需要处理时,立刻唤醒
  • main函数中,开启了运行循环,保证函数不会被结束,等待 ≠ 死循环

数据结构

  • NSRunLoop => Foundation
  • CFRunLoop => CoreFoundation

CFRunLoop:

  • name: 某一个runloopMode的名称,通过名称来找到模式
  • sources0: CFRunLoopSource => source0 手动唤醒
  • sources1: source1 具备唤醒线程的能力
  • observers: 观测时间点
  • timers:runloop的定时器

1 RunLoop -> n Model:

  • m Source
  • m Timer
  • m Observer

事件循环的实现机制

  1. 即将进入RunLoop
  2. 将要处理Timer/Source0事件
    通知Observer
  3. 处理Source0事件
  4. 如果有Source1要处理 -> 8. 处理唤醒时收到的消息
  5. 线程将要休眠
  6. 休眠、等待唤醒
    6.1 Source1
    6.2 Timer事件的回调
    6.3 外部手动唤醒
  7. 线程刚被唤醒
  8. 即将退出RunLoop

RunLoop的核心

RunLoop与NSTimer

NSCommonMode

RunLoop与多线程

  • 线程和RunLoop是一一对应的
  • 新建的线程默认是没有RunLoop的

怎样实现一个常驻线程

  1. 创建一个RunLoop
  2. 添加port/source给RunLoop
  3. 启动RunLoop

网络

大纲

HTTP协议
HTTPS与网络安全
TCP/UDP

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,695评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,569评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,130评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,648评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,655评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,268评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,835评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,740评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,286评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,375评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,505评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,185评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,873评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,357评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,466评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,921评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,515评论 2 359

推荐阅读更多精彩内容