自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(61)
  • 收藏
  • 关注

原创 “魔音智能去水印”隐私政策

为了让您快速地找到您所需要的业务并为此提供更优质的服务,我们可能会在应用启动或后台运行时收集您使用本APP的设备信息(包括设备名称和型号、设备识别码、操作系统和应用程序版本、分辨率、服务提供商网络ID、 网络身份标识信息(IP 地址等)、个人常用设备信息(包括硬件型号、软件列表、MAC地址、操作系统类型、惟一设备识别码(如IMEI/Android ID/IDFA))以便为您提供服务。此外,在注销账户后,我们将停止为您提供产品和服务,并根据您的要求,删除您的个人信息或匿名化处理,法律法规另有规定的除外。

2024-01-18 20:06:52 1759

原创 技术支持网站

技术支持网站

2022-06-29 15:17:41 220

原创 iOS-底层原理 38:离屏渲染的理解

屏幕显示图像的原理:高中物理应该学过显示器是如何显示图像的:需要显示的图像经过CRT电子枪以极快的速度一行一行的扫描,扫描出来就呈现了一帧画面,随后电子枪又会回到初始位置循环扫描,形成了我们看到的图片或视频。为了让显示器的显示跟视频控制器同步,当电子枪新扫描一行的时候,准备扫描的时发送一个水平同步信号(HSync信号),显示器的刷新频率就是HSync信号产生的频率。然后CPU计算好frame等属性,将计算好的内容交给GPU去渲染,GPU渲染好之后就会放入帧缓冲区。然后视频控制器会按照HSync信号逐

2022-01-19 16:15:44 561

原创 Swift探索11:协议Protocol

本文主要分析protocol的用法及底层存储结构协议的基本用法 【语法格式】:协议的语法格式 //协议的语法格式protocol MyProtocol { //body} class、struct、enum都可以遵守协议,如果需要遵守多个协议,可以使用逗号分隔 //1-2、class、struct、enum都可以遵守协议,如果需要遵守多个协议,可以使用逗号分隔struct CJLTeacher: Protocol1, Protocol2 { //body

2021-12-13 17:00:42 440

原创 Swift探索10:Optional&Equatable&Comparable&访问控制权限

本文主要分析Optional源码、Equatable+Comparable协议Optional分析swift中的可选类型(Optional),用于处理值缺失的情况,有以下两种情况 有值,且等于x 没有值 这点可以通过swift-source->Optional.swift源码(CMD+P,搜索Optional)源码来印证@frozenpublic enum Optional<Wrapped>: ExpressibleByNilLiteral {

2021-12-09 16:38:45 2292

原创 Swift探索9:逃逸闭包 & 非逃逸闭包

本文主要分析逃逸闭包 、非逃逸闭包、自动闭包逃逸闭包 & 非逃逸闭包逃逸闭包定义当闭包作为一个实际参数传递给一个函数时,并且是在函数返回之后调用,我们就说这个闭包逃逸了。当声明一个接受闭包作为形式参数的函数时,可以在形式参数前写@escaping来明确闭包是允许逃逸的 如果用@escaping修饰闭包后,我们必须显示的在闭包中使用self swift3.0之后,系统默认闭包参数就是被@nonescaping,可以通过SIL来验证 SIL验证 1、执行时

2021-12-09 16:31:22 1357

原创 Swift探索8:闭包的使用&捕获原理

本文主要分析闭包以及闭包捕获变量的原理闭包闭包是一个捕获了全局上下文的常量或者变量的函数,通俗来讲,闭包可以是常量也可以是函数 【全局函数是一种特殊的闭包】:定义一个全局函数,只是当前的全局函数并不捕获值 func test(){ print("test")} 【函数闭包】:下面的函数是一个闭包,函数中的incrementer是一个内嵌函数,可以从makeIncrementer中捕获变量runningTotal func makeIncrementer() -&g

2021-12-08 17:18:32 1207

原创 Swift探索7:Mirror源码解析

本文主要是分析Mirror的底层实现,以及根据Mirror底层原理仿写其结构的实现在Swift-进阶 06:反射Mirror & 错误处理文章中,我们介绍了Mirror的使用,即JSON解析,对此我们有如下一些疑问: 1、系统是如何通过Mirror获取对应的属性以及值的? 2、Swift众所周知是一门静态语言,系统在底层到底做了什么,使swift具有了反射的特性呢? 下面我们来对Mirror的底层实现进行探索Mirror底层源码分析反射的API主要是由两部分实现的

2021-12-07 16:18:17 425

原创 Swift探索6:错误处理&反射Mirror

本文主要介绍Mirror的使用以及使用Mirror进行JSON解析的错误处理反射Mirror反射:是指可以动态获取类型、成员信息,在运行时可以调用方法、属性等行为的特性, 在上面的分析中,我们已经知道,对于一个纯swift类来说,并不支持直接像OC runtime那样的操作 但是swift标准库依旧提供了反射机制,用来访问成员信息,即Mirror 一般使用class CJLTeacher: NSObject { var age: Int = 18}let mir

2021-12-06 17:18:15 248

原创 swift探索5:内存管理 & Runtime

本文主要介绍swift中的内存管理,涉及引用计数、弱引用、强引用、循环引用、Runtime等内存管理 - 强引用在swift中也是使用ARC来追踪和管理内存的,下面我们通过一个案例来进行分析class CJLTeacher { var age: Int = 18 var name: String = "CJL"}var t = CJLTeacher()var t1 = tvar t2 = t 查看t的内存情况,为什么其中的refCounts是0x00000006

2021-12-03 16:27:05 357

原创 iOS 底层原理 + Swift 文章汇总

1、对象底层:结构体+alloc分析iOS-底层原理 02:alloc & init & new 源码分析iOS-底层原理 03:objc4-781 源码编译 & 调试iOS-底层原理 04:NSObject的alloc 源码分析iOS-底层原理 05:内存对齐原理iOS-底层原理 06:malloc 源码分析 思路 2、对象的本质:isa+isa属性分析+类结构iOS-底层原理 07:isa与类关联的原理iOS-底层原理 08:类 & 类结构分析iOS-底层原..

2021-09-27 16:00:06 2405 2

原创 iOS-底层原理 37:组件化方案(二)

本文主要讲组件化之间是如何通讯的组件化通讯方案目前主流的主要有以下三种方式: 1、URL路由 2、target-action 3、protocol匹配 URL路由目前iOS上大部分路由工具都是基于URL匹配的,或者是根据命名约定,用runtime方法进行动态调用这些动态化的方案的优点是实现简单,缺点是需要维护字符串表,或者依赖于命名约定,无法在编译时暴露出所有问题,需要在运行时才能发现错误。URL路由方式主要是以蘑菇街为代表的的MGJRouter其实现思

2021-09-27 15:55:12 284

原创 iOS-底层原理 36:组件化方案(一)

组件化组件化其实就是将模块单独抽离、分层,并指定模块间的通讯方式,从而实现解耦的一种方式,主要运用与团队开发为什么需要组件化?主要有以下四个原因 1、模块间解耦 2、模块重用 3、提高团队协作开发效率 4、单元测试 当项目因为各种需求,越来越来时,如果此时的各个模块之间是互相调用,即你中有我,我中有你这种情况时,会造成高耦合的情况。一旦我们需要对某一块代码进行修改时,就会牵一发而动全身,导致项目难以维护其问题主要体现在以下几个方面: 1、修改某个

2021-09-27 15:54:54 897

原创 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 237

原创 iOS-底层原理 32:内存管理(一)

本文主要是分析内存管理中的内存管理方案,以及retain、retainCount、release、dealloc的底层源码分析ARC & MRCiOS中的内存管理方案,大致可以分为两类:MRC(手动内存管理)和ARC(自动内存管理)MRC 在MRC时代,系统是通过对象的引用计数来判断一个是否销毁,有以下规则 对象被创建时引用计数都为1 当对象被其他指针引用时,需要手动调用[objc retain],使对象的引用计数+1 当指针变量不再使用对

2021-09-27 07:57:10 760

原创 iOS-底层原理 31:启动优化之二进制重排

前提,在之前的两篇文章中,大致介绍了一些基本概念以及启动优化的思路,下面来着重介绍一个pre-main阶段的优化方案,即二进制重排,这个方案最开始是由于抖音的这篇文章抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超15%火起来的。二进制重排原理在虚拟内存部分,我们知道,当进程访问一个虚拟内存page,而对应的物理内存不存在时,会触发缺页中断(Page Fault),因此阻塞进程。此时就需要先加载数据到物理内存,然后再继续访问。这个对性能是有一定影响的。基于Page Fault,我

2021-09-25 17:53:43 755

原创 iOS-底层原理 30:启动优化之优化建议

启动启动的过程一般是指从用户点击app图标开始到AppDelegate 的didFinishLaunching方法执行完成为止,其中,启动也分为冷启动和热启动 冷启动:内存中不包含app相关数据的启动,一般我们可以通过重启手机来实现冷启动 热启动:是指杀掉app进程后,数据仍然存在时的启动 而我们这里所说的启动优化,一般是指冷启动情况下的,这种情况下的启动主要分为两部分: T1:pre-main阶段,即main函数之前,操作系统加载App可执行文件到内存,执行一系列的加载&a.

2021-09-24 10:00:36 385

原创 iOS-底层原理 29:启动优化之内存分页

虚拟内存 & 物理内存早期的数据访问是直接通过物理地址访问的,这种方式有以下两个问题: 1、内存不够用 2、内存数据的安全问题 内存不够用的方案:虚拟内存针对问题1,我们在进程和物理内存之间增加一个中间层,这个中间层就是所谓的虚拟内存,主要用于解决当多个进程同时存在时,对物理内存的管理。提高了CPU的利用率,使多个进程可以同时、按需加载。所以虚拟内存其本质就是一张虚拟地址和物理地址对应关系的映射表 每个进程都有一个独立的虚拟内存,其地址都是从0开始,大小是4G固定的

2021-09-23 07:39:43 566

原创 iOS-底层原理 35:界面优化方案

本文主要介绍界面卡顿的原理以及优化界面卡顿通常来说,计算机中的显示过程是下面这样的,通过CPU、GPU、显示器协同工作来将图片显示到屏幕上图像显示过程 1、CPU计算好显示内容,提交至GPU 2、GPU经过渲染完成后将渲染的结果放入FrameBuffer(帧缓存区) 3、随后视频控制器会按照VSync信号逐行读取FrameBuffer的数据 4、经过可能的数模转换传递给显示器进行显示 最开始时,FrameBuffer只有一个,这种情况下FrameB

2021-09-22 10:57:35 419

原创 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 641

原创 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 380

原创 iOS-底层原理 26:锁的原理

本文主要介绍常见的锁,以及synchronized、NSLock、递归锁、条件锁的底层分析锁借鉴一张锁的性能数据对比图,如下所示锁性能对比可以看出,图中锁的性能从高到底依次是:OSSpinLock(自旋锁) -> dispatch_semaphone(信号量) -> pthread_mutex(互斥锁) -> NSLock(互斥锁) -> NSCondition(条件锁) -> pthread_mutex(recursive 互斥递归锁) -> NSRe

2021-09-12 20:27:58 767

原创 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 787

原创 swift探索3: 内存分区&值类型&引用类型

值类型前提:需要了解内存五大区,内存五大区可以参考这篇文章iOS-底层原理 24:内存五大区,如下所示值类型-1 栈区的地址 比 堆区的地址 大 栈是从高地址->低地址,向下延伸,由系统自动管理,是一片连续的内存空间 堆是从低地址->高地址,向上延伸,由程序员管理,堆空间结构类似于链表,是不连续的 日常开发中的溢出是指堆栈溢出,可以理解为栈区与堆区边界碰撞的情况 全局区、常量区都存储在Mach-O中的__TEXT cString段 我

2021-09-01 17:04:01 455 1

原创 swift探索4: 方法调度

结构体和类的方法存储在哪里?下面来一一进行分析静态派发值类型对象的函数的调用方式是静态调用,即直接地址调用,调用函数指针,这个函数指针在编译、链接完成后就已经确定了,存放在代码段,而结构体内部并不存放方法。因此可以直接通过地址直接调用 结构体函数调试如下所示 打开打开demo的Mach-O可执行文件,其中的__text段,就是所谓的代码段,需要执行的汇编指令都在这里 对于上面的分析,还有个疑问:直接地址调用后面是符号,这个符号哪里来的?是从Mach-O文件中

2021-09-01 17:03:19 535

原创 iOS-底层原理 34:AutoReleasePool 底层分析

AutoReleasePool 自动释放池自动释放池是OC中的一种内存自动回收机制,它可以将加入AutoreleasePool中的变量release的时机延迟,简单来说,就是当创建一个对象,在正常情况下,变量会在超出其作用域的时立即release。如果将对象加入到了自动释放池中,这个对象并不会立即释放,会等到runloop休眠/超出autoreleasepool作用域{}之后才会被释放。其机制如下图所示AutoreleasePool机制图示 1、从程序启动到加载完成,主线程对应的runlo

2021-09-01 16:52:53 476

原创 swift探索2: swift属性

在swift中,属性主要分为以下几种 存储属性 计算属性 延迟存储属性 类型属性 存储属性存储属性,又分两种: 要么是常量存储属性,即let修饰 要么是变量存储属性,即var修饰 定义如下代码class CJLTeacher{ var age: Int = 18 var name: String = "CJL"}let t = CJLTeacher()其中代码中的age、name来说,都是变量存储属性,这一点可

2021-09-01 15:18:23 277

原创 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 639

原创 swift探索1:类、对象

为了探索swift类的本质,我们创建一个类并将文件编译,生成可读的SIL文件aclass Person { var name = "dotry" var age = 26}let p = Person()编译之后得到解析过程如下@main标识当前man.swift的入口函数,SIL中的 标识符名称以@作为前缀。 %0,%1……在SIL中也叫做寄存器,可以理解为平时代码中定义的常量,一旦赋值之后就不可以改变。如果SIL中还要继续使用,只有不断地累加数字。同时这里的寄存.

2021-08-25 14:20:47 561 1

原创 iOS-底层原理 23:GCD 之 函数与队列

本文的主要目的是理解不同队列与不同函数之间组合的情况GCD简介 GCD全称是Grand Central Dispatch 纯C语言,提供例如非常强大的函数 GCD优势 GCD是苹果公司为多核的并行运算提出的解决方案 GCD会自动利用更多的CPU内核(比如双核、四核) GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程) 程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码 【重点】用一句话总结GCD就是:将任务添加到队列

2021-08-25 07:17:17 307

原创 iOS-底层原理 22:多线程相关

本文的目的在于了解进程、线程、多线程、线程池等的基本概念及原理线程 和 进程线程和进程的定义线程线程时进程的基本执行单元,一个进程的所有任务都在线程中执行 进程要想执行任务,必须的有线程,进程至少要有一条线程 程序启动会默认开启一条线程,这条线程被称为 主线程 或者 UI线程进程进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用的且受保护的内存空间内 通过“活动监视器”可以查看mac系统中所开启的线程所以,可以简单的理解为:进程是线程的容器,

2021-08-21 16:57:13 250

原创 iOS-底层原理 21:内存五大区

在iOS中,内存主要分为栈区、堆区、全局区、常量区、代码区五大区域。如下图所示下面分别介绍这五大区栈区(Stack)定义 栈是系统数据结构,其对应的进程或者线程是唯一的 栈是向低地址扩展的数据结构 栈是一块连续的内存区域,遵循先进后出(FILO)原则 栈的地址空间在iOS中是以0X7开头 栈区一般在运行时分配 存储栈区是由编译器自动分配并释放的,主要用来存储 局部变量 函数的参数,例如函数的隐藏参数(id self,S

2021-08-19 20:22:01 290

原创 iOS-底层原理 20:KVO探索

KVO,全称为Key-Value observing,中文名为键值观察,KVO是一种机制,它允许将其他对象的指定属性的更改通知给对象。KVO是基于KVC基础之上在iOS日常开发中,经常使用KVO来监听对象属性的变化,并及时做出响应,即当指定的被观察的对象的属性被修改后,KVO会自动通知相应的观察者,那么KVO与NSNotificatioCenter有什么区别呢? 相同点 1、两者的实现原理都是观察者模式,都是用于监听 2、都能实现一对多的操作 不同点

2021-08-16 22:58:09 238

原创 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 312

原创 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 755

原创 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 387

原创 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 410

原创 iOS-底层原理 15:应用程序启动加载

本文的目的主要是分析dyld的加载流程,了解在main函数之前,底层还做了什么引子 创建一个project,在ViewController中重写了load方法,在main中加了一个C++方法,即kcFUnc,请问它们的打印先后顺序是什么? 运行程序,查看 load、kcFunc、main的打印顺序,下面是打印结果,通过结果可以看出其顺序是 load --> C++方法 --> main 为什么是这么一个顺序?按照常规的思维理解,main不是入口函数吗?为什么不是m.

2021-08-07 16:20:07 461

原创 iOS-底层原理 14:objc_msgSend实现方式之崩溃前挽救

引子在前面两篇文章中,分别分析了objc_msgSend的快速查找和慢速查找,在这两种都没找到方法实现的情况下,苹果给了两个建议动态方法决议:慢速查找流程未找到后,会执行一次动态方法决议 消息转发:如果动态方法决议仍然没有找到实现,则进行消息转发如果这两个建议都没有做任何操作,就会报我们日常开发中常见的方法未实现的崩溃报错,其步骤如下 定义LGPerson类,其中say666实例方法 和 sayNB类方法均没有实现 main中 分别调用LGPerson的实例方法say666 和类

2021-08-04 18:40:36 770 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 284

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除