- 博客(22)
- 收藏
- 关注
原创 IOS开发 Runloop机制
Runloop是维护事件循环来对事件/消息进行管理的对象,runloop提供了一个函数,线程只要执行了这个函数,就会一直处于这个函数内部 “接受消息->等待->处理” 的循环中,没有消息需要处理时,runloop就休眠,不占用CPU,有消息处理时,runloop就立刻被唤醒。总结:runloop(死循环)保证runloop所在的线程不退出。
2025-10-27 17:25:38
659
1
原创 Xcode开发的应用安装到手机的全过程
Bundle ID:应用的唯一标识,相当于应用的身份证号开发者证书:由苹果签发的数字证书,包含开发者公钥、teamID、有效期等,用来证明开发者身份描述文件(.mobileprovision):打包文件,包含允许安装的设备的UDID、关联的bundleID、对应的开发者证书、应用权限。
2025-10-17 15:28:01
378
原创 Day4 iOS应用从启动到退出的生命周期
创建UIWindow并设置rootViewController,通过makeKeyAndVisible使窗口成为“关键窗口”(接受键盘和事件)并显示,此时窗口开始渲染根控制器的视图。2、UIApplicationMain函数会创建UIApplication单例,创建AppDelegate,并将其设置为UIApplication的代理。6、启动完成,应用进入前台活跃状态,根控制器的viewDidAppear调用后,系统触发AppDelegate的。3、启动主线程的runloop,进入事件等待状态。
2025-10-15 19:45:40
109
原创 IOS中的应用缓存
存储在IOS的沙盒目录Library/Caches中,磁盘缓存占用的是手机的存储空间(类似电脑的硬盘),而非内存。内存缓存是应用进程内存的一部分,占用应用内存,供 CPU 快速访问。比如一个应用的内存上限是200MB,其中50MB用于图片内存缓存,那么这50MB就属于该应用的内存占用。应用缓存(图片缓存、网络请求缓存)的本质是为了加速数据访问而临时存储的数据,根据存储位置不同,分为两类。当完整的图片数据(二进制字节流)进入应用内存后,需要经过简单处理,为写入磁盘做准备,验证后的图片数据(
2025-10-13 15:15:55
140
原创 Day3 IOS中的UIResponder
在IOS中UIResponder类是用来响应用户的各种事件的,包括触摸事件、运动事件、远程控制事件,UIApplication、UIView、UIViewController这几个类都直接继承于UIResponder,UIWindow继承UIView,所以这些类以及他们的子类都可以响应事件,在IOS里,将这些能响应事件的对象称之为响应者。
2025-10-11 17:45:30
752
原创 Day2 iOS中的runtime
在runtime中,类被定义为指向objc_class结构体的指针。objc_class结构体中的第一个变量是isa指针,isa指针保存的是指向元类的指针,换句话说,class类的本质就是一个对象,称之为类对象。结构体的数据结构// 指针指向元类#if!__OBJC2__// 指向父类的指针// 类的名字// 类的版本信息,默认为 0long info;// 类的信息,供运行期使用的一些位标识// 该类的实例变量大小;// 该类的实例变量列表// 方法定义的列表// 方法缓存。
2025-10-09 16:18:37
610
原创 Day1 多线程GCD
我们需要异步并发执行两组任务时,当第一组任务执行完毕时才会执行第二组任务,这时用到栅栏方法,栅栏方法会等前边追加到并发队列中的所有任务执行完成之后才会将指定的任务追加到该异步队列中。所有的任务都是在主线程中按顺序执行的,因为是异步,所以主线程不会等,执行完队列外的任务之后去执行主队列中的任务。不会开启新线程,所有任务都是在当前线程(主线程)中执行,任务按顺序执行,执行完一个任务再执行下一个任务。主队列中的任务都是在主线程中执行的,平常所写的代码也是放入主队列中的,主线程按顺序执行主队列中的任务。
2025-09-28 16:22:32
721
原创 详解websocket
1、HTTP1.1是半双工的协议,只要客户端不问服务器就不答,所以对于服务器主动推送数据到客户端的场景不太友好,所以我们需要使用支持全双工的websocket协议。2、在HTTP1.1里可以通过不断定时轮询和长轮询实现服务器推送的效果3、对于网页游戏这种需要客户端和服务器频繁交互的场景,可以考虑使用websocket4、websocket只在握手的时候使用HTTP协议,之后和HTTP协议没有任何关系。
2024-06-01 11:39:11
487
原创 在4G物理内存的机器上申请8G的内存会怎样?
swap就是把一块磁盘空间当做内存来用,包含换入和换出两个过程。换出:把进程暂时不用的磁盘数据存储到磁盘中,并释放这些数据占用的内存换入:进程再次访问这些内存的时候,把他们从磁盘读到内存中来。
2024-05-28 09:37:46
791
原创 内存满了会发生什么?
在系统空闲内存不足的情况,进程申请了一个很大的内存,如果直接内存回收都无法回收处足够大的空闲内存,那么就会触发OOM机制,内核会根据算法选择一个进程杀掉。文件页的回收:对于干净页来说是直接释放内存,这个操作不会影响性能,而对于脏页,要先写到磁盘再释放内存,这个操作会发生磁盘IO,会影响系统性能。匿名页的回收:如果开启了swap机制,会先将不常访问的匿名页换出到磁盘中,下次访问时,再从磁盘换入到内存,这个操作是会影响性能的。因此,应该尽量回收文件页,回收文件页中的干净页是不会产生磁盘IO的。
2024-05-27 13:12:01
1212
原创 虚拟内存有什么作用?
1、虚拟内存可以使进程的运行内存超过其物理内存的大小,因为根据程序的局部性原理,,CPU访问内存有明显的重复访问的倾向性,每次用到的物理内存也就那么几页,所以只需要把用到的那几页加载进物理内存,对于那些不常使用到的内存,我们可以把它换出到物理内存之外,比如磁盘上的swap区域。2、每个进程的虚拟地址空间是相互独立的,进程没有办法访问到其他进程的页表,通过页表对虚拟页面和物理页框的映射关系,解决了多进程之间地址冲突的问题。虚拟内存的大小超过其物理内存的大小。避免多进程之间的地址冲突,通过页表。
2024-05-27 10:55:42
451
原创 malloc是如何分配内存的?
malloc库函数:用来动态分配内存malloc()分配的是虚拟内存,只有当访问到这块虚拟内存时,操作系统才会查询页表,发现虚拟内存对应的也没有在物理内存中,就会引发缺页中断,然后建立起虚拟内存页与物理内存页之间的映射关系。
2024-05-26 16:06:43
1213
原创 C++新特性-可变参数模板
另外在使用一元折叠时还需要主要空参数的情况,还是以sum函数为例,如果在调用函数的时候没有任何参数,那么就无法确定结果的返回类型,所以一定会编译失败。这个新方法叫折叠表达式。总结:可变参数模版这个特性可以说是新标准中最重要的模版相关的特性,丰富的包展开和折叠表达式功能也让模板元编程代码变得更加容易理解。可变参数模版是C++11标准引入的一个新特性,顾名思义就是类模板或函数模版的形参个数是可变的。并不是所有的情况都能进行包展开的,包展开需要特定的场景。一元向左折叠、二元向左折叠、一元向右折叠、二元向右折叠。
2024-05-18 16:43:29
591
原创 C++新特性-线程局部存储thread_local
线程局部存储简单来说就是将对象内存和线程关联在一起。对象在线程开始后分配内存,在线程结束时释放内存,每个对象相对于线程是独立的,并且不会相互干扰。Windows和Linux都有各自的办法分配线程局部存储。Windows跟线程局部存储相关的APITlsAlloc:分配未被使用的线程局部存储槽索引,这个索引是线程环境块中一个数组的索引,该数组就是用来存储线程相关的内存的TlsGetValue:根据索引获取数组的元素的值TlsSetValue:根据索引设置数组的元素的值。
2024-05-17 13:23:37
514
原创 C++新特性-类型别名和别名模板
相比于typedef,使用using声明别名模板就方便多了。1、C++11提供了一种更加方便清晰的方法声明类型别名。2、using声明别名模版。
2024-05-16 17:38:21
244
原创 C++新特性-结构化绑定
了解python的同学都知道,python可以利用元组来返回多个值,其实C++也可以利用元组类型来返回多个值.int main()int x, y;return 0;从上图可以看出这段代码可以返回一个元组,但是相对于python来说却麻烦很多。
2024-05-15 16:08:11
342
原创 C++中的定位放置new (placement new)
所以,与其说定位放置new操作是申请空间,还不如说是利用已经请好的空间,真正的申请空间的工作是在此之前完成的。定位生成对象是,会自动调用类A的构造函数,但是由于对象的空间不会自动释放(对象实际上是借用别人的空间),所以必须显示的调用类的析构函数,如本例中的p->~A()。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。但是,在某些特殊情况下,可能需要在程序员指定的特定内存创建对象,这就是所谓的“定位放置new”(placement new)操作。
2024-05-14 17:05:41
397
原创 C++11非受限联合类型Union
联合类型U有两个非平凡类型x3和x4,所以他们必须有自己的构造和析构函数,虽然这里的构造和析构什么也没做,但是至少保证代码可以编译通过,虽然代码能编过但是并不代表它是正确的,对于x3和x4而言并没有方法去初始化和销毁他们。可以看到U的构造函数构造了x3,并且在x3中主动调用了x3的析构函数,这样可以保证使用x3时是没有问题的,但是没办法使用其他成员,所以这样做也是有问题的。如上图所示,类型U的构造和析构什么都不做,而是在使用这些对象的时候使用place new的方法来构造他们,使用完之后手动调用析构。
2024-05-14 11:33:17
379
原创 lambda表达式
C++11才开始具备lambda表达式这种特性eg:int x = 5;return x*y;captures是捕获列表,它可以捕获当前函数所在作用域中零或多个变量params是参数列表specifiers是可选限定符,如mutable(允许在函数体内改变按值捕获的变量 或 调用非const类型修饰的成员函数)exception是可选异常说明符,可以使用noexcept来指明表达式lambda是否会抛出异常return 返回值类型body函数体。
2024-05-13 11:52:15
1126
原创 decltype说明符
typeid是标准里的关键字,使用typeid运算符可以在运行时返回一个类型为type_info的对象,对象中记录了类型的标识符和类型名。typeof并不是一个标准的关键字,他是在GCC扩展中用的,使用GCC编译器的程序员可以使用typeof静态的获取操作数的具体类型。总结,decltype的主要用途是推导实体和表达式的类型,难点是它的推导规则,因为它的推导规则和auto是有一些区别的。1、如果e是一个未加括号的标识符表达式 或 未加括号的类成员访问,则decltype(e)推断出的类型是e的类型T。
2024-05-12 11:19:31
406
1
原创 auto占位符
在C++11标准中,给auto赋予了一个新的含义,简单来说,就是使用auto声明的变量编译器会根据初始化表达式自动推断该变量的类型,或者是作为函数声明时返回类型的占位符。如下图。auto i = 5;//推断为intauto str = "hello auto" //推断为const char*auto sum(int a1, int a2)->int { //返回类型后置,auto为返回值占位符。
2024-05-11 15:12:26
495
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅