iOS底层
文章平均质量分 92
iOS底层学习之路
LinShunIos
这个作者很懒,什么都没留下…
展开
-
iOS 底层探索篇 ——block(上)
@[TOC](iOS 底层探索篇 —— block(上))1. block类型block一共有三种类型:全局block (NSGlobalBlock): 位于全局区,在block内部不使用外部变量,或者只使用静态变量和全局变量堆block (NSMallocBlock): 位于堆区,在block内部使用变量或者oc属性,并且赋值给强引用或者Copy修饰的变量栈block (NSStackBlock): 位于栈区,与MallocBlock一样,可以在内部使用局部变量或者oc属性。但是不能赋值给强引原创 2021-08-22 18:22:07 · 607 阅读 · 0 评论 -
iOS 底层探索篇 —— GCD 源码分析
iOS 底层探索篇 —— GCD 源码分析1. 死锁1.1 同步函数死锁串行并行1. 死锁所谓死锁,通常指有两个线程A和B都卡住了无法完成,都在等待对方完成任务后在执行。A不能完成是因为它在等待B完成。但B也不能完成,因为它在等待A完成。于是大家都无法完成任务,就导致了死锁(DeadLock)。1.1 同步函数死锁同步,异步区别能否开辟新线程任务回调是否具备异步性 - 同步性死锁情况的产生下面分析串行和并行执行同步函数的情况。串行上文说到同步函数实现会走到这里,这里看到dq_widt原创 2021-08-12 16:07:26 · 493 阅读 · 0 评论 -
iOS 底层探索篇 ——block(下)
@[TOC](iOS 底层探索篇 —— block(下))block底层源码block 编译成一个什么样的结构block invoke-> isa->签名 ->捕获 -> 保存 -> 释放1. block底层分析要探究block底层是什么样的一个结构,那么就定义一个block,然后xcrun 一下。xcrun之后,打开生成的cpp文件,看到生成的main函数。把函数的类型强转去掉之后得到下面的代码。这里看到 void(*block)(void) 等于__ma原创 2021-08-24 21:58:43 · 711 阅读 · 0 评论 -
iOS组件化
iOS组件化 ——(上)1. 组件化介绍CocoaPods1. 组件化介绍在一个项目越来越大,开发人员越来越多的情况下,项目会遇到很多问题。业务模块间划分不清晰,模块之间耦合度很大,非常难维护。所有模块代码都编写在一个项目中,测试某个模块或功能,需要编译运行整个项目。为了解决这些问题,就需要用到组件化。组件化的作用如下:模块间解耦模块重用提高团队协作开发效率单元测试并不是所有的项目都需要组件化,如果:项目较小,模块间交互简单,耦合少模块没有被多个外部模块引用,只是一个单独的原创 2021-09-18 16:30:41 · 762 阅读 · 0 评论 -
iOS 底层探索篇 —— GCD栅栏函数、信号量、调度组和Dispatch_Source
iOS 底层探索篇 —— GCD栅栏函数、信号量、调度组和soure原创 2021-08-16 15:56:52 · 1739 阅读 · 0 评论 -
iOS内存管理 —— 散列表和弱引用表
iOS内存管理 —— 散列表和弱引用表1. 散列表2. 弱引用表1. 散列表散列表的本质是哈希表。散列表在手机上有8张,在模拟器或者其他设备上为64张。散列表里面有锁,引用计数表和弱引用表。其中锁用来保证线程安全,引用计数表是用来存超过最大个数的引用计数的,弱引用表则是用来储存__weak修饰的变量和weak修饰的属性等。如果在整个系统中只有一张散列表,那么在使用过程中开表和关表,为了保证线程安全就要开锁和解锁,如果所有对象挤在一个表里,就会导致性能等消耗。多张表还可以及时回收相关内存。2. 弱引用表原创 2021-09-10 11:48:42 · 515 阅读 · 0 评论 -
iOS内存管理 —— 自动释放池和runloop
iOS内存管理 —— 自动释放池和runloop1. 自动释放池1.1 自动释放池介绍1.2 自动释放池底层原理autoreleaseNoPageautoreleaseFullPage1. 自动释放池1.1 自动释放池介绍自动释放池是OC中的一种内存自动回收机制,它可以延迟加入AutoreleasePool中的变量release的时机,即当我们创建了一个对象,并把他加入到了自动释放池中时,他不会立即被释放,会等到一次runloop结束或者作用域超出autoreleasepool{}之后再被释放1.2原创 2021-09-13 16:47:55 · 1039 阅读 · 0 评论 -
iOS启动优化 —— LLVM编译流程 & Clang插件开发
iOS启动优化 —— LLVM编译流程 & Clang插件开发1. LLVM1.1 LLVM概述1.2 传统编译器设计1.3 ios的编译器架构1.4 LLVM的设计1.5 Clang2. 编译流程3. 编译阶段3.1 词法分析3.2 语法分析3.3 生成中间代码IR1. LLVM1.1 LLVM概述LLVM是架构编译器的框架系统,以C++编写而成,用于优化任意程序语言编写的程序的编译时间(compile-time)、链接时间(link-time)、运行时间(run-time)以及空闲时间(原创 2021-08-27 15:24:10 · 526 阅读 · 0 评论 -
iOS内存管理 —— TaggedPointer 和 retain、release 流程分析
iOS内存管理 —— TaggedPointer 和 retain、release 流程分析1. 内存布局内存五大区2. 内存管理方案2.1 模拟器调试TaggedPointer2.2 真机调试TaggedPointer3. NONPOINTER_ISA3.1 retain 流程分析3.2 release 流程分析4. 面试题1. 内存布局内存五大区栈: 存放局部变量,参数,指针,函数,地址一般以0x7开头。栈区的内存通过sp寄存器来定位的。堆:存放alloc、new开辟内存的对象,地址一般以0x原创 2021-09-07 17:54:36 · 473 阅读 · 0 评论 -
iOS 底层探索篇 —— GCD函数和队列
iOS 底层探索篇 —— GCD函数和队列1. 面试题主队列队列和线程1. 面试题这里的函数会输出什么呢?这里的答案是A:1230789,因为这里是串行队列,那么任务就会按顺序执行,所以打印出来的是1230789。主队列主队列(Main queue)是与主线程关联的调度队列,是一种串行队列(Serial),与UI相关的操作必须放在Main queue中执行,用dispatch_get_main_queue()可以获取到主队列。队列和线程一个线程中可以有多个队列,每个队列中可以执行多个任务,队列原创 2021-08-06 17:56:13 · 351 阅读 · 0 评论 -
iOS启动优化 —— 二进制重排
iOS启动优化 —— 理论1. app启动2. 虚拟内存 & 物理内存3. 缺页中断(pagefault)1. app启动启动的过程一般是指从用户点击app图标开始到AppDelegate 的didFinishLaunching方法执行完成为止,其中,启动也分为冷启动和热启动:冷启动:第一次打开app或app被杀死后重新打开叫冷启动(走didFinishLaunchWithOptions方法)热启动:app在后台且存活的状态下,再次打开app叫热启动(不走didFinishLaunchWi原创 2021-09-01 15:33:36 · 883 阅读 · 1 评论 -
iOS启动优化 —— Clang插桩
iOS启动优化 —— Clang插桩上文说到二进制重排可以减少缺页中断(pagefault)的次数而达到优化启动时间的效果,那么如何知道启动的时候用到了哪些符号呢?这就要用到clang插桩了。原创 2021-09-03 10:55:04 · 986 阅读 · 0 评论 -
iOS界面优化 ——卡顿检测和优化方案
iOS界面优化 ——卡顿检测和优化方案1. 卡顿原理2. 卡顿监听。1. 卡顿原理卡顿,也就是掉帧。当UIView被绘制时,cpu执行drawrect,通过context将数据写入backingstore。当backingstore 写完后,通过 render server 交给gpu去渲染,渲染的东西放到framebuffer里面,然后通过Video Controller交给monitor进行显示。说到底cpu就是做绘制的操作把内容放到缓存里,gpu负责从缓存里读取数据然后渲染到屏幕上。最开始时,原创 2021-09-15 16:28:04 · 1741 阅读 · 0 评论 -
iOS 底层探索篇 —— 锁
iOS 底层探索篇 —— 锁1. 锁的简介2. ios 8大锁3. @synchronized1. 锁的简介我们在使用多线程的时候多个线程可能会访问同一块资源,这样就很容易引发数据错乱和数据安全等问题。而合理的运用锁可以保证每次只有一个线程访问这一块资源,这样就可以解决多线程引发的数据问题。2. ios 8大锁将各种锁循环加锁开锁100000次,计算出耗费的时间来看一下各种锁的性能。从输出可以看到各种锁的性能差别。3. @synchronized在实际开发中,@synchronized用的最经原创 2021-08-18 11:29:48 · 385 阅读 · 0 评论 -
iOS 底层探索篇 ——八大锁的分析
iOS 底层探索篇 —— 八大锁的分析1. 锁的类型2. 锁的应用3. 锁的底层实现NSConditionLock的探索1. 锁的类型自旋锁:线程反复检查锁变量是否可用。由于线程在这一过程中保持执行, 因此是一种忙等待。一旦获取了自旋锁,线程会一直保持该锁,直至显式释放自旋锁。 自旋锁避免了进程上下文的调度开销,因此对于线程只会阻塞很短时间的场合是有效的。互斥锁:是一种用于多线程编程中,防止两条线程同时对同一公共资源(比 如全局变量)进行读写的机制有互斥和同步两个特点。当一个线程在进行任务的时候原创 2021-08-22 13:58:16 · 446 阅读 · 0 评论 -
iOS 底层探索篇 —— 多线程原理
iOS 底层探索篇 —— 多线程(一)1. 线程和进程1.1 线程和进程的定义1.2 线程和进程的关系2. 多线程2.1 多线程的意义2.2 多线程的原理2.3 多线程技术方案2.3 多线程生命周期2.4 线程池原理1. 线程和进程1.1 线程和进程的定义线程线程是进程的基本执行单元,一个进程的所有任务都在线程中执行。进程要想执行任务,必须得有线程,进程至少要有一条线程。程序启动会默认开启一条线程,这条线程被称为主线程或 UI 线程进程进程是指在系统中正在运行的一个应用程序。每原创 2021-08-02 17:53:08 · 284 阅读 · 0 评论 -
iOS 底层探索篇 —— dyld加载流程(上)
iOS 底层探索篇 —— dyld加载流程1. 应用程序加载1.1库1.2 编译过程1.3 DYLD(链接器)1.4 APP 启动流程2. dyld探索1. 应用程序加载1.1库每个程序的运行都会依赖一些基础的库,比如说UIKit,CoreFoundation等,库是一些可执行的二进制文件,能被操作系统加载到内存中。库有两种形式,就是静态库(.a , .lib)和动态库(.so , .dll),两个库主要表现在链接的区别。静态库:静态库在编译时加载,在链接时会完整的复制到可执行文件中,此时的静态原创 2021-07-08 23:27:11 · 691 阅读 · 0 评论 -
iOS 底层探索篇 ——Runtime-objc_msgSend流程分析 - 慢速查找流程 (上)
iOS 底层探索篇 ——Runtime-objc_msgSend流程分析(下)接着上篇的代码分析真机中探寻objc_msgSend_objc_msgSend_uncached接着上篇的代码分析//这里的p12 是第一次要找的index((_cmd ^ (_cmd >> 7)) & mask)//左移4位相当于*16,p10是buckets的首地址,也就是将p10平移到第一次要查找的地方//然后储存到p12里面。 add p12, p10, p12, LSL #(1+PTRSHI原创 2021-06-30 10:43:33 · 172 阅读 · 0 评论 -
iOS 底层探索篇 ——OC底层面试解析
iOS 底层探索篇 ——OC底层面试解析1. 关联对象在那里移除2. Load方法在哪里调用3. 方法的调用顺序4. Runtime是什么5. 方法的本质,sel是什么?IMP是什么?两者之间的关系又是什么?6. 能否向编译后的得到的类中增加实例变量? 能否向运行时创建的类中添加实例变量7. [self class]和[super class]的区别以及原理分析8. 内存平移问题压栈1. 关联对象在那里移除关联对象在objc_removeAssociatedObjects方法里面的_object_rem原创 2021-07-23 18:14:20 · 359 阅读 · 1 评论 -
iOS 底层探索篇 ——Runtime-消息转发
iOS 底层探索篇 ——Runtime-消息转发快速转发流程慢速转发流程上文说到instrumentObjcMessageSends,那么这个方法是怎么来的呢。在log_and_fill_cache里面有一个判断SUPPORT_MESSAGE_LOGGING。进去logMessageSend方法,看到这里在往/tmp/msgSends-%d写入。那么也就是说只要objcMsgLogEnabled,那么就会写入。搜索一下objcMsgLogEnabled。发现在instrumentObjcMess原创 2021-07-05 15:35:36 · 487 阅读 · 0 评论 -
iOS 底层探索篇 —— KVC 底层原理
iOS 底层探索篇 —— KVC 底层原理1. Method Swizzling的坑与应用1.1 method-swizzling 是什么?1.2 坑点坑点1:method-swizzling使用过程中的确保执行一次解决方案坑点2:子类没有实现,父类实现了解决方案坑点3:父类子类都没有实现解决方案class_replaceMethod, addMethod, method_exchangeImplementations 源码2.KVC2.1KVC 设值流程图1. Method Swizzling的坑与应原创 2021-07-25 09:27:54 · 718 阅读 · 0 评论 -
iOS 底层探索篇 —— 内存字节对齐分析
结构体内存对齐获取内存大小的三种方式sizeofclass_getInstanceSizemalloc_sizesizeofsizeof是一个操作符,不是函数我们一般用sizeof计算内存大小时,传入的主要对象是数据类型,这个在编译器的编译阶段(即编译时)就会确定大小而不是在运行时确定。sizeof最终得到的结果是该数据类型占用空间的大小class_getInstanceSize是runtime提供的api,用于获取类的实例对象所占用的内存大小,并返回具体的字节数,其本质就是获取原创 2021-06-08 22:18:10 · 386 阅读 · 0 评论 -
iOS 底层探索篇 —— 类的原理分析-下
iOS 底层探索篇 —— 类的原理分析-下成员变量 & 属性 & 实例变量Type encoding成员变量 & 属性 & 实例变量属性(property):在OC中是通过@property开头定义,且是带下划线成员变量 + setter + getter方法的变量成员变量(ivar):在OC的类中{}中定义的,为基本数据类型,且没有下划线的变量实例变量:通过当前对象类型,具备实例化的变量,是一种特殊的成员变量,例如 NSObject、UILabel、UI原创 2021-06-21 16:27:09 · 287 阅读 · 0 评论 -
iOS 底层探索篇 ——Runtime-objc_msgSend流程分析 - 快速查找流程
iOS 底层探索篇 ——Runtime(下)补充:在lldb中调用方法为什么mask为7作业:代码运行方法会不会插入结束符号objc_msgSend流程解释1解释2解释3解释4解释5解释6补充:在lldb中调用方法为什么mask为7我们看到在代码中调用方法的情况,那么在lldb中调用方法呢?试一下:这里的mask变成了7,这是为什么呢?mask变成了7,那么代表着,cache一定进行了一次类似的扩容,那么其必然就会到insert里面,那么我们去insert实现里面。之前证明了,当缓存方法到了3/原创 2021-06-27 23:24:50 · 380 阅读 · 0 评论 -
iOS 底层探索篇 —— OC对象本质 & noPointerIsa
iOS 底层探索篇 —— OC对象本质 & noPointerIsa对象的本质探索Clang操作代码实例对象的本质Class类型的本质类型getter 和 setter联合体位域位域结构体(struct)所有变量是共存的联合体(union)中是各变量是互斥的noPointerIsa对象的本质探索Clangclang是一个由Apple主导编写,基于LLVM的C/C++/OC的编译器操作代码实例通过这个指令,就可以把main.m 编译成 main.cpp 文件,可以更好的观察底层的一些结原创 2021-06-11 17:57:56 · 541 阅读 · 0 评论 -
iOS 底层探索篇 —— 类的原理分析-上
iOS 底层探索篇 —— 类的原理分析类的原理分析从 isa 开始探索 - isa走位链元类用MachOView(烂苹果)进行探索元类继承链类的原理分析类的原理分析主要是分析 isa以及 继承关系.从 isa 开始探索 - isa走位链首先我们先获得isa的掩码 0x00007ffffffffff8ULL,然后获得对象的地址,拿到对象的isa。至此,我们得到了isa的掩码:0x00007ffffffffff8ULL以及对象的isa:0x011d800100008365,然后我们将这两个进行与运原创 2021-06-17 17:30:53 · 354 阅读 · 0 评论 -
iOS 底层探索篇 —— Cache分析
iOS 底层探索篇 —— 类的原理分析-下Cache底层分析cache结构猜测LLDB证明cache结构哈希表Cache底层分析cache结构猜测之前我们在获取bits的时候,是通过内存平移,那么我们获取cache,也可以通过内存平移。isa 和 superclass 都是8位,所以需要平移16位才能获得cache。我们在lldb中得到LGPerson类的地址,然后平移16位,并将其转为cache_t *类型,然后将里面的内容打印出来。这里我们就获得了cache_t的数据。对比一下在源码原创 2021-06-24 09:32:45 · 389 阅读 · 0 评论 -
iOS 底层探索篇 ——类的加载原理补充,类拓展和关联对象
iOS 底层探索篇 ——类的加载原理补充,类拓展和关联对象1.分类加载是否需要排序2.methodList的数据结构3.主类没有实现load方法,分类实现load方法时的数据加载4.class_ro_t5.类扩展6.关联对象1.分类加载是否需要排序由上一篇文章知道,在方法列表中,2个分类的方法的数组指针是在主类之前的,并且数组指针里面是经过排序的。首先添加2个分类,并且类和2个分类都有一个方法叫做testfunc1。运行,看到getMethodNoSuper_nolock里面。看到这里是遍历查找。原创 2021-07-21 18:46:27 · 356 阅读 · 1 评论 -
iOS 底层探索篇 ——Runimte 运行时&方法的本质
iOS 底层探索篇 —— Cache分析-下何时进行insert何时进行insert上文讲了insert这个方法,那么到底什么时候进行插入呢。我们在源码中搜索->insert,看看insert方法什么时候被调用。发现都不是要找的方法。那么现在我们就需要去cache_t的insert方法的实现里面打断点,然后运行一下,就可以得到insert是被谁调用的了。这里可以看到insert的上一步是log_and_fill_cache,那么insert大概率就是在这个里面被调用的,我们点进去看一下。原创 2021-06-25 00:49:18 · 302 阅读 · 0 评论 -
iOS 底层探索篇 —— dyld加载流程(下)
iOS 底层探索篇 —— dyld加载流程(下)1. sNotifyObjCMapped,sNotifyObjCMapped1.1 sNotifyObjCMapped 的调用1.2 sNotifyObjCInit 的调用1.3 CXX 方法的调用1. sNotifyObjCMapped,sNotifyObjCMapped上文说到_objc_init中调用了_dyld_objc_notify_register(&map_images, load_images, unmap_image)对regis原创 2021-07-11 12:03:13 · 383 阅读 · 0 评论 -
iOS 底层探索篇 —— KVO 底层原理(上)
iOS 底层探索篇 ——KVO 底层原理KVO注册一个kvo移除一个kvo手动和自动 kvo一对多可变数组观察kvo 原理NSKVONotifying_LGPersonKVOKVO(Key Value Observing, 键值观察)是Objective-C对观察者模式的实现,每次当被观察对象的某个属性值发生改变时,注册的观察者便能获得通知。注册一个kvoobserver:观察者 也就是被观察对象发生改变时通知的接收者keyPath:被观察的属性名options:参数 这里一般选择NSK原创 2021-07-30 00:29:17 · 528 阅读 · 2 评论 -
iOS 底层探索篇 ——类的加载原理(中)
iOS 底层探索篇 ——类的加载原理(中)上回说到readClass 里面给类加上了名字,那么ro,rw是在哪里加的呢?回到_read_images打上断点一点一点探究。在remap classes 这里打上断点后运行,发现没有进去。往下走,看到objc_msgSend_fixup,和类无关就跳过不看。继续往下走discover protocols也和类无关不看。在往下看到protocol references,也和类无关,继续往下走。discover categories,分类,继续跳过。继续往下原创 2021-07-16 18:28:58 · 255 阅读 · 0 评论 -
iOS 底层探索篇 ——类的加载原理(下)
iOS 底层探索篇 ——类的加载原理(下)1. 为什么要有ro,rw,rwe2. cls->data()3. extAllocIfNeeded & attachCategories4.分类的懒加载类和分类都实现load类实现load和分类不实现load类不实现load和分类实现load类和分类都不实现load5. 4种不同情况下的分类加载类和分类都实现load1. 为什么要有ro,rw,rwero属于cleanmemory,在编译即确定的内存空间,只读,加载后不会改变内容的空间rw属原创 2021-07-20 15:57:15 · 423 阅读 · 0 评论 -
iOS 底层探索篇 ——Runtime-objc_msgSend流程分析 - 慢速查找流程 (下)
iOS 底层探索篇 ——Runtime-objc_msgSend流程分析 - 慢速查找流程 (下)方法无法找到流程分析动态方法决议为什么两次tryCache方法无法找到流程分析上文说到,如果所有的父类都找完了还没找到方法,那么imp就会设为forward_imp,那么继续往下走,看到会返回imp也就是forward_imp。看到forward_imp在方法开头有进行赋值。接着寻找_objc_msgForward_impcache,发现进入__objc_msgForward。接着搜索__obj原创 2021-07-01 18:32:53 · 345 阅读 · 0 评论 -
iOS 底层探索篇 ——类的加载原理(上)
iOS 底层探索篇 ——类的加载原理(上)1. objc_init 做了什么1. objc_init 做了什么上文说到了objc_init调用了_dyld_objc_notify_register,初始化了dyld 里面的sNotifyObjCMapped,sNotifyObjCInit,sNotifyObjCUnmapped函数并对 sNotifyObjCMapped,sNotifyObjCInit直接进行了调用,那么objc_init还做了什么呢?首先看到environ_init,这里面主要做了原创 2021-07-14 09:51:50 · 419 阅读 · 0 评论 -
iOS 底层探索篇 —— KVO 底层原理(下)
iOS 底层探索篇 —— KVO 底层原理(下)1. 自定义KVO1.1 lg_addObserver1.2 lg_removeObserver2. 自定义函数式KVO3. KVO自动销毁机制4. FBKVOController1. 自定义KVO创建一个NSObject分类,并添加三个方法,lg_addObserver,lg_observeValueForKeyPath和lg_removeObserver。1.1 lg_addObserver接下来就是方法的实现。那么对于lg_addObserve原创 2021-07-31 17:12:30 · 318 阅读 · 0 评论 -
IOS —— Crash分析
常见crash类型容器越界使用未初始化的变量用户授权问题选择器方法未定义子线程刷新uiKVO数据类型不匹配内存溢出野指针死循环原创 2021-10-27 14:33:04 · 3051 阅读 · 0 评论