![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
ios底层原理探索
文章平均质量分 85
ios底层原理探索
changcongcong_ios
这个作者很懒,什么都没留下…
展开
-
iOS-底层原理 38:离屏渲染的理解
屏幕显示图像的原理:高中物理应该学过显示器是如何显示图像的:需要显示的图像经过CRT电子枪以极快的速度一行一行的扫描,扫描出来就呈现了一帧画面,随后电子枪又会回到初始位置循环扫描,形成了我们看到的图片或视频。为了让显示器的显示跟视频控制器同步,当电子枪新扫描一行的时候,准备扫描的时发送一个水平同步信号(HSync信号),显示器的刷新频率就是HSync信号产生的频率。然后CPU计算好frame等属性,将计算好的内容交给GPU去渲染,GPU渲染好之后就会放入帧缓冲区。然后视频控制器会按照HSync信号逐原创 2022-01-19 16:15:44 · 432 阅读 · 0 评论 -
iOS-底层原理 31:启动优化之二进制重排
前提,在之前的两篇文章中,大致介绍了一些基本概念以及启动优化的思路,下面来着重介绍一个pre-main阶段的优化方案,即二进制重排,这个方案最开始是由于抖音的这篇文章抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超15%火起来的。二进制重排原理在虚拟内存部分,我们知道,当进程访问一个虚拟内存page,而对应的物理内存不存在时,会触发缺页中断(Page Fault),因此阻塞进程。此时就需要先加载数据到物理内存,然后再继续访问。这个对性能是有一定影响的。基于Page Fault,我原创 2021-09-25 17:53:43 · 624 阅读 · 0 评论 -
iOS-底层原理 30:启动优化之优化建议
启动启动的过程一般是指从用户点击app图标开始到AppDelegate 的didFinishLaunching方法执行完成为止,其中,启动也分为冷启动和热启动 冷启动:内存中不包含app相关数据的启动,一般我们可以通过重启手机来实现冷启动 热启动:是指杀掉app进程后,数据仍然存在时的启动 而我们这里所说的启动优化,一般是指冷启动情况下的,这种情况下的启动主要分为两部分: T1:pre-main阶段,即main函数之前,操作系统加载App可执行文件到内存,执行一系列的加载&a.原创 2021-09-24 10:00:36 · 242 阅读 · 0 评论 -
iOS-底层原理 29:启动优化之内存分页
虚拟内存 & 物理内存早期的数据访问是直接通过物理地址访问的,这种方式有以下两个问题: 1、内存不够用 2、内存数据的安全问题 内存不够用的方案:虚拟内存针对问题1,我们在进程和物理内存之间增加一个中间层,这个中间层就是所谓的虚拟内存,主要用于解决当多个进程同时存在时,对物理内存的管理。提高了CPU的利用率,使多个进程可以同时、按需加载。所以虚拟内存其本质就是一张虚拟地址和物理地址对应关系的映射表 每个进程都有一个独立的虚拟内存,其地址都是从0开始,大小是4G固定的原创 2021-09-23 07:39:43 · 428 阅读 · 0 评论 -
iOS-底层原理 35:界面优化方案
本文主要介绍界面卡顿的原理以及优化界面卡顿通常来说,计算机中的显示过程是下面这样的,通过CPU、GPU、显示器协同工作来将图片显示到屏幕上图像显示过程 1、CPU计算好显示内容,提交至GPU 2、GPU经过渲染完成后将渲染的结果放入FrameBuffer(帧缓存区) 3、随后视频控制器会按照VSync信号逐行读取FrameBuffer的数据 4、经过可能的数模转换传递给显示器进行显示 最开始时,FrameBuffer只有一个,这种情况下FrameB原创 2021-09-22 10:57:35 · 302 阅读 · 0 评论 -
iOS-底层原理 28:LLVM编译流程和Clang插件开发
本文主要是理解LLVM的编译流程以及clang插件的开发LLVMLLVM是架构编译器的框架系统,以C++编写而成,用于优化任意程序语言编写的程序的编译时间(compile-time)、链接时间(link-time)、运行时间(run-time)以及空闲时间(idle-time)。对开发者保持开放,并兼容已有脚本传统编译器设计源码 Source Code + 前端 Frontend + 优化器 Optimizer + 后端 Backend(代码生成器 CodeGenerator)+ 机器码 M原创 2021-09-18 17:34:04 · 516 阅读 · 0 评论 -
iOS-底层原理 37:组件化方案(二)
本文主要讲组件化之间是如何通讯的组件化通讯方案目前主流的主要有以下三种方式: 1、URL路由 2、target-action 3、protocol匹配 URL路由目前iOS上大部分路由工具都是基于URL匹配的,或者是根据命名约定,用runtime方法进行动态调用这些动态化的方案的优点是实现简单,缺点是需要维护字符串表,或者依赖于命名约定,无法在编译时暴露出所有问题,需要在运行时才能发现错误。URL路由方式主要是以蘑菇街为代表的的MGJRouter其实现思原创 2021-09-27 15:55:12 · 202 阅读 · 0 评论 -
iOS-底层原理 36:组件化方案(一)
组件化组件化其实就是将模块单独抽离、分层,并指定模块间的通讯方式,从而实现解耦的一种方式,主要运用与团队开发为什么需要组件化?主要有以下四个原因 1、模块间解耦 2、模块重用 3、提高团队协作开发效率 4、单元测试 当项目因为各种需求,越来越来时,如果此时的各个模块之间是互相调用,即你中有我,我中有你这种情况时,会造成高耦合的情况。一旦我们需要对某一块代码进行修改时,就会牵一发而动全身,导致项目难以维护其问题主要体现在以下几个方面: 1、修改某个原创 2021-09-27 15:54:54 · 727 阅读 · 0 评论 -
iOS-底层原理 34:AutoReleasePool 底层分析
AutoReleasePool 自动释放池自动释放池是OC中的一种内存自动回收机制,它可以将加入AutoreleasePool中的变量release的时机延迟,简单来说,就是当创建一个对象,在正常情况下,变量会在超出其作用域的时立即release。如果将对象加入到了自动释放池中,这个对象并不会立即释放,会等到runloop休眠/超出autoreleasepool作用域{}之后才会被释放。其机制如下图所示AutoreleasePool机制图示 1、从程序启动到加载完成,主线程对应的runlo原创 2021-09-01 16:52:53 · 380 阅读 · 0 评论 -
iOS-底层原理 33:内存管理(二)
本文主要是通过定时器来梳理强引用的几种解决方案强应用(强持有)假设此时有两个界面A、B,从Apush到B界面,在B界面中有如下定时器代码。当从Bpop回到A界面[图片上传中...(E70D3F5D-8815-4138-BFDD-017B1BFCE0E7.png-6861f8-1609331145410-0)]时,发现定时器没有停止,其方法仍然在执行,为什么?self.timer = [NSTimer timerWithTimeInterval:1 target:self selecto...原创 2021-09-27 15:53:04 · 168 阅读 · 0 评论 -
iOS-底层原理 32:内存管理(一)
本文主要是分析内存管理中的内存管理方案,以及retain、retainCount、release、dealloc的底层源码分析ARC & MRCiOS中的内存管理方案,大致可以分为两类:MRC(手动内存管理)和ARC(自动内存管理)MRC 在MRC时代,系统是通过对象的引用计数来判断一个是否销毁,有以下规则 对象被创建时引用计数都为1 当对象被其他指针引用时,需要手动调用[objc retain],使对象的引用计数+1 当指针变量不再使用对原创 2021-09-27 07:57:10 · 558 阅读 · 0 评论 -
iOS-底层原理 27:Block底层原理
本文主要介绍block的类型、循环引用的解决方法以及block底层的分析block 类型block主要有三种类型 __NSGlobalBlock__:全局block,存储在全局区 void(^block)(void) = ^{ NSLog(@"CJL");};NSLog(@"%@", block);此时的block无参也无返回值,属于全局blockimage __NSMallocBlock__:堆区block,因为block既是函数,也是对象 int原创 2021-09-15 19:40:52 · 288 阅读 · 0 评论 -
iOS-底层原理 26:锁的原理
本文主要介绍常见的锁,以及synchronized、NSLock、递归锁、条件锁的底层分析锁借鉴一张锁的性能数据对比图,如下所示锁性能对比可以看出,图中锁的性能从高到底依次是:OSSpinLock(自旋锁) -> dispatch_semaphone(信号量) -> pthread_mutex(互斥锁) -> NSLock(互斥锁) -> NSCondition(条件锁) -> pthread_mutex(recursive 互斥递归锁) -> NSRe原创 2021-09-12 20:27:58 · 632 阅读 · 0 评论 -
iOS-底层原理 25:GCD底层原理
本文是队列创建、同步/异步函数、单例、信号量以及调度组的底层原理分析队列创建下面我们在libdispatch.dylib去探索队列是如何创建的底层源码分析 在源码中搜索dispatch_queue_create dispatch_queue_tdispatch_queue_create(const char *label, dispatch_queue_attr_t attr){ return _dispatch_lane_create_with_target(label原创 2021-09-07 08:24:19 · 527 阅读 · 0 评论 -
iOS-底层原理 24:GCD常用举例
dispatch_after- (void)cjl_testAfter{ /* dispatch_after表示在某队列中的block延迟执行 应用场景:在主队列上延迟执行一项任务,如viewDidload之后延迟1s,提示一个alertview(是延迟加入到队列,而不是延迟执行) */ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatc原创 2021-08-29 22:39:23 · 537 阅读 · 0 评论 -
iOS-底层原理 23:GCD 之 函数与队列
本文的主要目的是理解不同队列与不同函数之间组合的情况GCD简介 GCD全称是Grand Central Dispatch 纯C语言,提供例如非常强大的函数 GCD优势 GCD是苹果公司为多核的并行运算提出的解决方案 GCD会自动利用更多的CPU内核(比如双核、四核) GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程) 程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码 【重点】用一句话总结GCD就是:将任务添加到队列原创 2021-08-25 07:17:17 · 257 阅读 · 0 评论 -
iOS-底层原理 22:多线程相关
本文的目的在于了解进程、线程、多线程、线程池等的基本概念及原理线程 和 进程线程和进程的定义线程线程时进程的基本执行单元,一个进程的所有任务都在线程中执行 进程要想执行任务,必须的有线程,进程至少要有一条线程 程序启动会默认开启一条线程,这条线程被称为 主线程 或者 UI线程进程进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用的且受保护的内存空间内 通过“活动监视器”可以查看mac系统中所开启的线程所以,可以简单的理解为:进程是线程的容器,原创 2021-08-21 16:57:13 · 163 阅读 · 0 评论 -
iOS-底层原理 21:内存五大区
在iOS中,内存主要分为栈区、堆区、全局区、常量区、代码区五大区域。如下图所示下面分别介绍这五大区栈区(Stack)定义 栈是系统数据结构,其对应的进程或者线程是唯一的 栈是向低地址扩展的数据结构 栈是一块连续的内存区域,遵循先进后出(FILO)原则 栈的地址空间在iOS中是以0X7开头 栈区一般在运行时分配 存储栈区是由编译器自动分配并释放的,主要用来存储 局部变量 函数的参数,例如函数的隐藏参数(id self,S原创 2021-08-19 20:22:01 · 219 阅读 · 0 评论 -
iOS-底层原理 19:KVC探索
KVC的全称是Key-Value Coding,翻译成中文是 键值编码,键值编码是由NSKeyValueCoding非正式协议启用的一种机制,对象采用该协议来间接访问其属性。既可以通过一个·字符串key来访问某个属性·。这种间接访问机制补充了实例变量及其相关的访问器方法所提供的直接访问。KVC 相关API常用方法主要有以下四个常用的方法通过key设值/取值//直接通过Key来取值- (nullable id)valueForKey:(NSString *)key;//通过Key来设原创 2021-08-15 22:46:48 · 235 阅读 · 0 评论 -
iOS-底层原理 20:KVO探索
KVO,全称为Key-Value observing,中文名为键值观察,KVO是一种机制,它允许将其他对象的指定属性的更改通知给对象。KVO是基于KVC基础之上在iOS日常开发中,经常使用KVO来监听对象属性的变化,并及时做出响应,即当指定的被观察的对象的属性被修改后,KVO会自动通知相应的观察者,那么KVO与NSNotificatioCenter有什么区别呢? 相同点 1、两者的实现原理都是观察者模式,都是用于监听 2、都能实现一对多的操作 不同点原创 2021-08-16 22:58:09 · 169 阅读 · 0 评论 -
iOS-底层原理 16:应用程序启动加载之类加载
本文的主要目的是理解类的相关信息是如何加载到内存的,其中重点关注map_images和load_images_read_images 源码实现_read_images主要是主要是加载类信息,即类、分类、协议等,进入_read_images源码实现,主要分为以下几部分: 1、条件控制进行的一次加载 2、修复预编译阶段的@selector的混乱问题 3、错误混乱的类处理 4、修复重映射一些没有被镜像文件加载进来的类 5、修复一些消息 6、当..原创 2021-08-08 22:15:39 · 340 阅读 · 0 评论 -
iOS-底层原理 18:关联对象底层原理探索
其底层原理的实现,主要分为两部分: 通过objc_setAssociatedObject设值流程 通过objc_getAssociatedObject取值流程 关联对象-设值流程 在分类LG中重写属性cate_name的set、get方法,通过runtime的属性关联方法实现 运行程序,断点断在main中cate_name赋值处 继续往下运行,断在分类的setCate_name方法中 其中objc_setAssociatedObject方法有四原创 2021-08-13 16:24:21 · 552 阅读 · 0 评论 -
iOS-底层原理 17:应用程序启动加载之分类加载
本篇主要研究分类是如何加载到类中的,以及分类和类搭配使用的情况分类的本质前提:在main中定义LGperson的分类LG我们通过clang探索分类的本质 clang -rewrite-objc main.m -o main.cpp 查看底层编译,即 main.cpp, 其中分类的 类型是_category_t 分类的倒数第二个0,表示的是没有协议,所以赋值为0 搜索struct _category_t,如下所示 其中有两个method_list_t,分别表示实例.原创 2021-08-10 22:13:58 · 288 阅读 · 0 评论 -
iOS-底层原理 15:应用程序启动加载
本文的目的主要是分析dyld的加载流程,了解在main函数之前,底层还做了什么引子 创建一个project,在ViewController中重写了load方法,在main中加了一个C++方法,即kcFUnc,请问它们的打印先后顺序是什么? 运行程序,查看 load、kcFunc、main的打印顺序,下面是打印结果,通过结果可以看出其顺序是 load --> C++方法 --> main 为什么是这么一个顺序?按照常规的思维理解,main不是入口函数吗?为什么不是m.原创 2021-08-07 16:20:07 · 382 阅读 · 0 评论 -
iOS-底层原理 14:objc_msgSend实现方式之崩溃前挽救
引子在前面两篇文章中,分别分析了objc_msgSend的快速查找和慢速查找,在这两种都没找到方法实现的情况下,苹果给了两个建议动态方法决议:慢速查找流程未找到后,会执行一次动态方法决议 消息转发:如果动态方法决议仍然没有找到实现,则进行消息转发如果这两个建议都没有做任何操作,就会报我们日常开发中常见的方法未实现的崩溃报错,其步骤如下 定义LGPerson类,其中say666实例方法 和 sayNB类方法均没有实现 main中 分别调用LGPerson的实例方法say666 和类原创 2021-08-04 18:40:36 · 582 阅读 · 1 评论 -
iOS-底层原理 13:objc_msgSend实现方式之慢速查找
objc_msgSend 慢速查找流程分析慢速查找-汇编部分在快速查找流程中,如果没有找到方法实现,无论是走到CheckMiss还是JumpMiss,最终都会走到__objc_msgSend_uncached汇编函数在objc-msg-arm64.s文件中查找__objc_msgSend_uncached的汇编实现,其中的核心是MethodTableLookup(即查询方法列表),其源码如下STATIC_ENTRY __objc_msgSend_uncachedUNWIND __objc_原创 2021-08-02 21:56:05 · 202 阅读 · 0 评论 -
iOS-底层原理 12:方法查询之快速查找
Runtime 介绍runtime称为运行时,它区别于编译时 运行时 是代码跑起来,被装载到内存中的过程,如果此时出错,则程序会崩溃,是一个动态阶段 编译时 是源代码翻译成机器能识别的代码的过程,主要是对语言进行最基本的检查报错,即词法分析、语法分析等,是一个静态的阶段 runtime的使用有以下三种方式,其三种实现方法与编译层和底层的关系如图所示 通过OC代码,例如 [person sayNB] 通过NSObject方法,例如isKindOfClass 通原创 2021-07-31 09:26:36 · 279 阅读 · 0 评论 -
iOS-底层原理 10:底层经典题目分析
【面试题】iskindOfClass & isMemberOfClass 的理解我们通过源码得知源码分析总结 isKindOfClass 类方法:元类(isa) --> 根元类(父类) --> 根类(父类) --> nil(父类) 与 传入类的对比 实例方法:对象的类 --> 父类 --> 根类 --> nil 与 传入类的对比 isMemberOfClass 类方法: 类的元类 与 传入类 对比 实例.原创 2021-07-27 23:40:54 · 126 阅读 · 0 评论 -
iOS-底层原理 11:cache_t 分析
前两节分析了objc_class中isa和bits,这节课主要分析cachecache中存储的是什么?首先,我们需要知道cache中存储的到底是什么?查看cache_t的源码,发现分成了3个架构的处理,其中真机的架构中,mask和bucket是写在一起,目的是为了优化,可以通过各自的掩码来获取相应的数据 CACHE_MASK_STORAGE_OUTLINED 表示运行的环境 模拟器 或者 macOS CACHE_MASK_STORAGE_HIGH_16 表示运行环境是 64位的真机原创 2021-07-29 22:24:03 · 238 阅读 · 0 评论 -
iOS-底层原理 09:关键字strong©&weak底层分析
在clang编译的cpp文件中可以发现 strong & copy & weak 修饰的属性在编译的底层代码中是有区别的用clang将main.m文件编译成main.cpp,然后发现copy 和strong修饰的属性的set方法是有区别的copy的赋值是通过objc_setProperty,而strong的赋值时通过self + 内存平移在LLVM中搜索”objc_setProperty,找到如下所示的getOptimizedSetPropertyFn方法中从这里即可看.原创 2021-07-26 22:59:03 · 253 阅读 · 0 评论 -
iOS-底层原理 08:方法签名和attribute简写含义
clang中的方法签名clang中编译后,方法列表的这些字符的含义是什么以@16@0:8为例@16表示返回字符串占用16个字节 -- 第二个@ 占8字节, sel 占8字节 第一个@ 表示 返回值 16 表示 总共占用的字节数16字节 第二个@:第一个参数 id -- @ 统配类型 typedef struct objc_object *id 0 -- 从0开始 0-8 : -- 代表sel,方法编号 8 -- 8-16 而v24@0:8@16中的原创 2021-07-25 20:54:04 · 351 阅读 · 0 评论 -
iOS-底层原理 07:类属性&方法&变量结构分析
类 的分析类的分析 主要是分析 isa的走向 以及 继承关系准备工作定义两个类继承自NSObject的类CJLPerson,@interface CJLPerson : NSObject{ NSString *hobby;}@property (nonatomic, copy) NSString *cjl_name;- (void)sayHello;+ (void)sayBye;@end@implementation CJLPerson- (void)sayHe原创 2021-07-22 22:34:28 · 360 阅读 · 0 评论 -
iOS-底层原理 06: cls 与类的关联原理
联合体(union)构造数据类型的方式有以下两种:结构体(struct) 联合体(union,也称为共用体)结构体结构体是指把不同的数据组合成一个整体,其变量是共存的,变量不管是否使用,都会分配内存。 缺点:所有属性都分配内存,比较浪费内存,假设有4个int成员,一共分配了16字节的内存,但是在使用时,你只使用了4字节,剩余的12字节就是属于内存的浪费 优点:存储容量较大,包容性强,且成员之间不会相互影响 联合体联合体也是由不同的数据类型组成,但其变量是互斥的,所有的原创 2021-07-21 18:51:53 · 357 阅读 · 0 评论 -
iOS-底层原理 05: OC对象本质
在探索oc对象本质前,先了解一个编译器:clangClang clang是一个由Apple主导编写,基于LLVM的C/C++/OC的编译器 主要是用于底层编译,将一些文件``输出成c++文件,例如main.m 输出成main.cpp,其目的是为了更好的观察底层的一些结构 及 实现的逻辑,方便理解底层原理。 探索对象本质在main中自定义一个类LGPerson,有一个属性name@interface LGPerson : NSObject@property (nonatomi原创 2021-07-21 15:12:09 · 191 阅读 · 0 评论 -
iOS-底层原理 03:NSObject的alloc 源码分析
主要NSObject中的alloc是与自定义类的alloc的源码流程的区别,以及为什么NSObject中的alloc不走源码工程。在上一篇文章中分析了alloc的源码,这篇文章是作为对上一篇文章的补充,去探索为什么NSObject的alloc方法不走源码工程。NSObject的alloc无法进入源码的问题 首先在objc4-781可编译源码中的main函数中增加一个NSObject定义的对象,NSObject 和 LGPersong同时加上断点 在alloc的源码实现中加一个断点,同原创 2021-07-20 16:31:16 · 179 阅读 · 0 评论 -
iOS-底层原理 01:源码探索的三种方式
本文主要介绍下源码探索的三种方法1、符号断点直接跟流程 2、通过按住control+step into 3、汇编跟流程下面详细讲下这三种方法是如何查找到函数所在的源码库,以alloc为例1、符号断点直接跟流程 通过下alloc的符号断点 选择断点Symbolic Breakpoint 符号断点中输入 alloc main中的CJLPerson处 加一个断点 在走到这部分断点之前,需要关闭上面新增.原创 2021-07-20 16:11:03 · 224 阅读 · 0 评论 -
iOS-底层原理 02:alloc & init & new 源码分析
本文主要探索alloc的底层实现原理:源码下载大家可以通过Apple source在 路径自行下载objc4-781源码,但是通过官网下载的源码有报错问题,有时间的小伙伴可以参考https://www.jianshu.com/p/2fae148f015f进行修改报错。 同时给大家准备好了修改好的源码:https://github.com/chenjialin1016/objc4-debugTest,笔者使用的是objc4-818.2中的KCObjectBuild进行编译我们在代码全局中搜索...原创 2021-07-16 13:33:49 · 292 阅读 · 0 评论 -
iOS-底层原理 04:内存对齐原理
什么是内存对齐:内存对齐是一种在计算机内存中排列数据、访问数据的一种方式。它包含基本数据对齐和结构体数据对齐 。内存对齐的规则内存对齐的各个属性占用内存情况那我们在项目中进行实际的分析一下如上图我们分析的内存大小,那我们使用sizeof看看计算是否正确与我们计算的一致...原创 2021-07-20 10:21:02 · 200 阅读 · 0 评论