- 博客(99)
- 收藏
- 关注

原创 OC底层文章汇总
底层源码探索方式OC底层探索(一):alloc、init、new源码分析对象底层:结构体+alloc分析OC底层探索(二) :源码探索的三种方式OC底层探索(三) 内存对齐原理对象的本质:isa+isa属性分析+类结构OC底层探索(四) ISA的结构与类的关联、ISA走位分析OC底层探索(五) 类的结构分析OC底层探索(六) isa 经典面试题分析OC底层探索(七) cache_t分析方法的本质:消息发送,即objc_msgSend流程分析OC底层探索(八)objc_msgSend 流
2020-10-14 10:44:18
680

原创 iOS-- 离屏渲染的解析与合理使用
什么是离屏渲染APP的渲染流程是CPU将图片解码 -> frame buffer(帧缓冲区) -> 视频控制器读取显示,然后把图片丢掉。如下图:但是在某些情况下无法把渲染结果直接写入frame buffer,而是先暂存在另外的内存区域Offscreen Buffer,之后再写入frame buffer,那么这个过程被称之为离屏渲染。如下图:iOS中渲染的底层是由OpenGL/Metal来完成的,在OpenGL/Metal中有一种渲染方法是油画渲染,就是在渲染过程中根据深度值由大到小进行
2020-07-07 23:58:38
568

原创 浅谈图像撕裂问题及解决方法
图像撕裂问题及解决方法什么是图像撕裂就是一张图片在显示的时候分成了两半,即出现断层。如下图:根据字符串获取sel;SEL sel = NSSelectorFromString(@“surfaceUpdated:”);2.class_respondsToSelector()判断当前类是否存在SEL,返回值boolclass_respondsToSelector(self.class, sel)3.performSelector详细参考简书介绍动态调用方法performSelector是运行时系统负责去找方法的,在编译时候不做任何校
2021-04-03 14:41:15
269
原创 iOS 面试记录
1、atomic与nonatomic 的区别nonatomic非原子属性非线程安全,适合内存小的移动设备atomic原子属性(线程安全),针对多线程设计的,默认值保证同一时间只有一个线程能够写入(但是同一个时间多个线程都可以取值)atomic 本身就有一把锁(自旋锁) 单写多读:单个线程写入,多个线程可以读取线程安全,需要消耗大量的资源iOS 开发的建议所有属性都声明为 nonatomic尽量避免多线程抢夺同一块资源 尽量将加锁、资源
2021-02-23 23:32:35
200
原创 Xcode中的环境变量
$(BUILT_PRODUCTS_DIR)build成功后的,最终产品路径--可以在Build Settings参数的Per-configuration Build Products Path项里设置$(TARGET_NAME)目标工程名称$(SRCROOT)工程根目录(一般为.xcodeproj所在目录)$(PROJECT_DIR).xcodeproj所在目录$(CURRENT_PROJECT_VERSION)当前工程版本号@executable_path可执行文件所在目录@loa
2021-02-04 22:04:22
552
原创 swift进阶(五)协议
协议的用法语法格式protocol MyProtocol{ //body}class、struct、enum都可以遵守协议,多个协议,使用逗号分隔struct Person: Protocol1, Protocol2{//body}协议中添加属性协议同时要求一个属性必须明确是可读的或者 可读的和可写的属性要求是变量属性,不能使用let声明protocol MyProtocol{ var age : Int{ get } var name : String{
2021-01-03 18:01:55
261
原创 swift进阶(四)闭包底层探索
Swift进阶文章汇总在文章swift进阶(四)闭包的使用介绍了闭包的使用,那么闭包底层是什么样的呢?那今天让我们探究一番。1. 闭包捕获上下文先看以下代码打印的值应该是多少?func makeIncrementer() -> () -> Int { var runningTotal = 10 func incrementer() -> Int { runningTotal += 1 return runningTotal .
2020-12-27 18:01:36
595
1
原创 swift进阶(四)闭包的使用
Swift进阶文章汇总1.什么是闭包闭包是一个捕获了上下文的常量或者是变量的函数。闭包是 引用类型闭包分为以下几种:闭包表达式尾随闭包逃逸闭包自动闭包函数是一种特殊的闭包,函数不会捕获值。闭包可以当做变量,也可以当做参数传递2. 闭包表达式闭包表达式就是一个匿名函数,从上下文中捕获 变量和常量。闭包表达式是是swift的语法,使用闭包表达式能更简洁的传达信息。比如:{ (age: Int) in return age }优点:利用上.
2020-12-27 14:39:10
305
原创 swift进阶(三)swift指针
Swift进阶文章汇总swift中的指针分为两类typed pointer 指定数据类型指针,即 UnsafePointer<T>,其中T表示泛型raw pointer 未指定数据类型的指针(原生指针) ,即UnsafeRawPointerswift与OC指针对比如下:原生指针原生指针:是指未指定数据类型的指针,有以下说明对于指针的内存管理是需要手动管理的指针在使用完需要手动释放原生指针的使用//原生指针//对于指针的内存管理是需要手动管理的//.
2020-12-20 18:24:30
740
原创 swift进阶(二):swift方法的调用
结构体结构体的常用写法//***** 写法一 *****struct QTeacher { var age: Int = 18 func teach(){ print("teach") }}var t = QTeacher()//***** 写法二 *****struct QTeacher { var age: Int func teach(){ print("teach") }}var
2020-12-20 16:04:54
1385
原创 Swift进阶(一):类和属性
1、类SIL在底层流程中,OC代码和SWift代码时通过不同的编译器进行编译,然后通过LLVM,生成.o可执行文件,如下所示OC中通过clang编译器,编译成IR,然后再生成可执行文件.o(即机器码)swift中通过swiftc编译器,编译成IR,然后再生成可执行文件下面是Swift中的编译流程,其中SIL(Swift Intermediate Language),是Swift编译过程中的中间代码,主要用于进一步分析和优化Swift代码。如下图所示,SIL位于在AST和LLVM IR之间
2020-12-12 14:14:40
1229
1
原创 OC底层探索(二十六)界面优化
界面卡顿的原理由于iOS的渲染机制,会造成掉帧的情况,所以界面会卡顿。请参考文章浅谈图像撕裂问题及解决方法,此文章中就不过多的解释界面卡顿的原理了。卡顿检测1. YYKit库YYKit下载地址YYkit主要是使用CADisplayLink 绑定到runloop上进行监听渲染次数。2. 监听runloop监听runloop事物处理的时间,主要监听runloop的kCFRunLoopBeforeSources和kCFRunLoopAfterWaiting这两个状态值,如果监听到了超过两秒
2020-11-28 01:39:23
388
原创 OC底层探索(二十五)内存管理 --强引用
OC底层文章汇总强引用环境准备此时有两个界面A、B,从A push 到B界面,在B界面中有如下定时器代码。当从B界面pop回到A界面时,发现定时器没有停止,其方法仍然在执行。self.timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(fireHome) userInfo:nil repeats:YES];[[NSRunLoop currentRunLoop] addTimer:self.timer.
2020-11-26 22:34:13
220
原创 OC底层探索(二十四)内存管理 -- 引用计数底层分析
OC底层文章汇总在OC底层探索(十八)内存五大区中了解了栈区、堆区、全局区、常量区和代码区五大区的分布,那么今天来分析一下内存管理的引用计数。taggedpointer小对象类型
2020-11-24 23:49:31
703
原创 OC底层探索(二十三)Block用法及原理
Block的使用return_type表示返回的对象/关键字等(可以是void,并省略)blockName表示block的名称var_type表示参数的类型(可以是void,并省略)varName表示参数名称return_type表示返回的对象/关键字等(可以是void,并省略)blockName表示block的名称var_type表示参数的类型(可以是void,并省略)Block声明及定义语法varName表示参数名称return_type (^blockNam
2020-11-10 23:44:15
868
原创 OC底层探索(二十二)八大锁
OC底层文章汇总锁的种类在OC中锁分为互斥锁和自旋锁两种。互斥锁用于保护临界区,确保同一时间,只有一条线程能够执行如果代码中只有一个地方需要加锁,大多都使用 self,这样可以避免单独再创建一个锁对象加了互斥锁的代码,当新线程访问时,如果发现其他线程正在执行锁定的代码,新线程就会进入休眠针对互斥锁,还需要注意以下几点:互斥锁的锁定范围,应该尽量小,锁定范围越大,效率越差能够加锁的任意 NSObject对象锁对象一定要保证所有的线程都能够访问自旋锁.
2020-11-10 22:41:52
925
原创 OC底层探索 -- clang的使用和iOS底层源码的地址
进入文件目录执行xcrun -sdk iphonesimulator clang -rewrite-objc xxxx.m
2020-11-07 19:17:05
241
原创 OC底层探索(二十一)GCD异步、GCD同步、单例、信号量、调度组、栅栏函数等底层分析
OC底层文章汇总在上一篇OC底层探索(十九) 多线程文章中介绍了OC中GCD的使用,那么GCD的底层原理是什么呢?1、单例源码1.1 前期准备新建一个GCD单例在这里插入代码片1.2 源码分析查看dispatch_once,发现dispatch_once_f函数在这里插入代码片????查看dispatch_once_f,参数分别为在这里插入代码片????????????????2、异步线程3、GCD 函数的调用3.1 前期准备写一个GCD线程,在函
2020-11-07 17:38:20
1181
原创 OC底层探索(二十)GCD队列的底层原理
OC底层文章汇总在上一篇OC底层探索(十九) 多线程文章中介绍了OC中GCD的使用,那么GCD的底层原理是什么呢?1、 队列的种类队列分为串行队列和并行队列。串行队列dispatch_queue_create("queue1", NULL); // 串行 并行队列//并行dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT); 2、队列源码分析2.1 前提准备创建4个队列,并打印查看每个队列.
2020-11-03 23:33:45
739
原创 OC底层探索(十九) 多线程
1.进程与线程1.1 进程进程是指在系统中正在运行的一个应用程序每个进程之间是独立的,每个进程均运行在其专用的且受保护的内存空间内目前在iOS中,一个进程就是一个app。1.2 线程线程是进程的基本执行单元,一个进程的所有任务都在线程中执行.进程要想执行任务,必须得有线程,进程至少要有一条线程程序启动会默认开启一条线程,这条线程被称为主线程或 UI 线程1.3 进程与线程的关系地址空间:同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间。资源拥有:同一进程内的线
2020-11-01 21:41:31
1479
6
原创 OC底层探索(十八)内存五大区
内存五大区栈区主要存储运行程序的中间结果和断点信息。包括一些函数的参数和局部变量的值。由系统自动分配和释放。在内存中,栈是一块形同数组的连续存储空间,数据的存储遵循“先进后出”的原则,栈区域的地址由高地址向低地址增长,也就是说,存放的数据越多,栈顶的地址越低。堆区就是那些由 new alloc 创建的对象所分配的内存块,它们的释放系统不会主动去管,由我们的开发者去告诉系统什么时候释放这块内存(一个对象引用计数为0是系统就会回销毁该内存区域对象)。一般一个 new 就要对应一个 rele
2020-10-31 10:28:07
255
原创 OC底层探索(十六) KVO底层原理
OC底层文章汇总KVO全称KeyValueObserving,是苹果提供的一套事件通知机制。允许对象监听另一个对象特定属性的改变,并在改变时接收到事件。由于KVO的实现机制,所以对属性才会发生作用,一般继承自NSObject的对象都默认支持KVO。KVO和NSNotificationCenter都是iOS中观察者模式的一种实现。区别在于,相对于被观察者和观察者之间的关系,KVO是一对一的,而不一对多的。KVO对被监听对象无侵入性,不需要修改其内部代码即可实现监听。KVO可以监听单个属性的变化,也可.
2020-10-27 23:52:33
509
原创 OC底层探索(十五)KVC底层原理
OC底层文章汇总KVC的全称是Key-Value Coding,翻译成中文是 键值编码,键值编码是由NSKeyValueCoding非正式协议启用的一种机制,对象采用该协议来间接访问其属性。既可以通过一个字符串key来访问某个属性。这种间接访问机制补充了实例变量及其相关的访问器方法所提供的直接访问。KVC 相关API常用方法通过key 设值/取值//直接通过Key来取值- (nullable id)valueForKey:(NSString *)key;//通过Key来设值 - (.
2020-10-27 22:06:20
336
原创 OC底层面试题
一.类扩展 与 分类 的区别1.category 分类专门用来给类添加新的方法不能使用正常方法给类添加成员属性,即使添加了成员属性,也无法取到。注意:其实可以通过runtime 给分类添加属性,即属性关联,重写setter、getter方法。分类中用@property 定义变量,只会生成变量的setter、getter方法的声明,不能生成方法实现 和 带下划线的成员变量2.extension 类扩展类的扩展可以说成是特殊的分类,也可称作匿名分类可以给类添加成员变量,但是为私有变量可以
2020-10-25 15:22:55
512
原创 OC底层探索(十四)_objc_init分析——load_images分析
OC底层文章汇总load_images分析在objc源码中,查看load_images源码,查看 prepare_load_methods和call_load_methods方法voidload_images(const char *path __unused, const struct mach_header *mh){ if (!didInitialAttachCategories && didCallDyldNotifyRegister) { di
2020-10-24 17:47:30
292
原创 OC底层探索(十三)_objc_init分析——类的加载(下)
OC底层文章汇总在文章OC底层探索(十二)_objc_init分析——类的加载(上)中,有介绍到_read_Image的readClass方法是没有对rw(read write)、ro(read only)、rwe(read write ext)进行操作,那么在哪对类进行操的呢?类的加载rw、ro和rweapp在使用类时,是需要在磁盘中app的二进制文件中读取类的信息,二进制文件中的类存储了类的元类、父类、flags和方法缓存,如下图那么类的额外信息(name、方法、协议和实例变量等)存
2020-10-18 22:49:00
775
原创 OC底层探索(十二)_objc_init分析——类的加载上
_objc_init源码void _objc_init(void){ static bool initialized = false; if (initialized) return; initialized = true; // fixme defer initialization until an objc-using image is found? environ_init(); tls_init(); static_init();
2020-10-14 00:01:46
669
1
原创 OC底层探索(十一)dyld流程
引入在ViewController中添加Load方法,输出打印。#import "ViewController.h"@interface ViewController ()@end@implementation ViewController+ (void)load{ NSLog(@"%s",__func__);}- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup af
2020-10-11 22:41:02
907
原创 OC底层探索(十)objc_msgSend 流程之方法的动态方法决议和消息的快速转发、慢速转发
前提在前面两篇文章OC底层探索(八)objc_msgSend 流程之方法快速查找和OC底层探索(九)objc_msgSend 流程之方法慢速查找中,分别分析了objc_msgSend的快速查找和慢速查找,在这两种都没找到方法实现的情况下,苹果给了两个建议动态方法决议:慢速查找流程未找到后,会执行一次动态方法决议消息转发:如果动态方法决议仍然没有找到实现,则进行消息转发环境准备新建Person类Person.h@interface Person : NSObject@property (n
2020-09-26 17:57:03
1610
原创 OC底层探索(九)objc_msgSend 流程之方法慢速查找
在上篇文章OC底层探索(八)objc_msgSend 流程之方法快速查找中探索了在cache中查找方法,如果查找命中,一切好说;如果没有查找到那么就会执行慢速查找,并存入缓存中,以便下次查找。执行慢速查找的时机在缓存中没有找到需要执行的方法,则会进入__objc_msgSend_uncached,我们来看源码:源码我们明显可以看到下面执行MethodTableLookup函数,源码:源码接下来就会执行_looUpImpOrForward,但是在objc-msg-arm64.s文件中
2020-09-26 14:29:24
300
原创 OC底层探索(八)objc_msgSend 流程之方法快速查找
OC runtime运行时在探索objc_msgSend时,我们需要先了解OC的runtime机制。runtime简介runtime 是 OC底层的一套C/C++的API(引入 <objc/runtime.h> 或<objc/message.h>),编译器最终都会将OC代码转化为运行时代码,通过终端命令编译.m 文件:clang -rewrite-objc xxx.m可以看到编译后的xxx.cpp(C++文件)。runtime 交互的三种方式Objective-C C
2020-09-20 18:19:09
713
原创 OC底层探索(七) cache_t分析
cache_t 源码在OC底层探索(五) 类的结构分析文章中,我们分析objc_class源码时,有提到过其属性 cache_t cache属性的大小为16字节。那么我们今天就着重分析以下cache_t到底是干什么的。准备工作在LGPerson类中申请两个方法:@interface LGPerson : NSObject-(void)sayHello;-(void)sayCode;在main.h中调用这两个方法,并打上断点int main(int argc, const char
2020-09-17 23:34:10
343
原创 OC底层探索(六) isa 经典面试题分析
OC底层探索(六)关于isa走位图的面试题问题一:执行class_getInstanceMethod、class_getClassMethod和class_getMethodImplementation打印出什么?Person.h文件- (void)sayHello;+ (void)sayHappy;Main.h文件const char *className = class_getName(pClass); Class metaClass = objc_getMetaClass(cla
2020-09-17 21:22:01
285
原创 OC底层探索(五) 类的结构分析
objc_object 与 objc_class我们在使用clang方式将OC代码编译成cpp文件(c++)时,我们会发现类是的底层编译是结构体,如:NSObject的底层编译是NSObject_IMPL结构体。其中Class是isa指针类型,而Class是objc_class类型的变量;struct NSObject_IMPL{ Class isa;};typedef struct objc_class *Class;在objc4源码中搜索objc_class的定义,我们就会发现o
2020-09-14 09:55:51
385
原创 OC底层探索(四) ISA的结构与类的关联、ISA走位分析
联合体概念联合体又称共用体,联合体是由多种类型的变量组成,但多个变量共用一块内存,所以变量之间是互斥的,联合体中的变量只能存在一个有值,如果有别的变量被赋值,那么之前的变量就会被覆盖掉。案例 union { char bits; // 增加代码的可读性,相对于这个联合体就是说这一个字节的各个位都是做什么用的,占用几位,总共是用一个字节而已 struct { // 位域名 : 位域长 ch
2020-09-10 23:17:33
526
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人