iOS使用频率最高的内存管理有哪几种(ios,移动开发)

时间:2024-05-03 19:41:07 作者 : 石家庄SEO 分类 : 移动开发
  • TAG :

    iOS%E4%BD%BF%E7%94%A8%E9%A2%91%E7%8E%87%E6%9C%80%E9%AB%98%E7%9A%84%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E6%9C%89%E5%93%AA%E5%87%A0%E7%A7%8D

block内存分为三种类型:

_NSConcreteGlobalBlock(全局)

_NSConcreteStackBlock(栈)

_NSConcreteMallocBlock(堆)

1)对于_NSConcreteStackBlock_NSConcreteGlobalBlock类型
_NSConcreteStackBlock_NSConcreteGlobalBlock这两种类型的block,我们可以手动创建,如下所示:

那么我们怎么确定这两个block,就是我们所说的两种类型的block呢,我们可以使用clang -rewrite-objc xxx.m(报错可以使用详细命令:clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk xxxxx.m)编译转换成C++实现,就可以看到转换完的结果,如下所示:

可以看出可以看出globalBlock是_NSConcreteGlobalBlock类型,即在全局区域创建,block变量存储在全局数据存储区;stackBlock是_NSConcreteStackBlock类型,即在栈区创建。
2)对于_NSConcreteMallocBlock类型
NSConcreteMallocBlock类型的内存是通过_NSConcreteStackBlock类型的block copy得到的,那么哪些类型会对block进行copy呢?

block作为返回值

block作为属性,使用copy修饰时(strong修饰符不会改变block内存类型)

block为strong类型,且捕获了外部变量时。

对于作为参数传递的block,其类型是什么呢?

我们可以发现函数参数的block为什么类型,block在函数中就是什么类型。

1)enumerateObjectsUsingBlock中的对象

2)__autoreleasing 修饰的对象

3)array、dictiongnary、stringWithString等非init或者new方法生成的对象

以上类型实验结果:

注意:这里面的实验结果不一样,在arm64上、array、dictiongnary、stringWithString等方法生成的对象,在自动缓存池中只能看见第一个对象,而armv7的机型上,可以看见所有的,不知这里是什么原因,有知道的欢迎告诉我

两个常用的调试命令

1)系统通过runloop创建的autoreleasePool
runloop 可以说是iOS 系统的灵魂。内存管理/UI 刷新/触摸事件这些功能都需要 runloop 去管理和实现。runloop是通过线程创建的,和线程保持一对一的关系,其关系是保存在一个全局的 Dictionary 里。线程刚创建时并没有 RunLoop,如果你不主动获取,那它一直都不会有。RunLoop 的创建是发生在第一次获取时,RunLoop 的销毁是发生在线程结束时。你只能在一个线程的内部获取其 RunLoop(主线程除外)。

runloop和autoreleasePool又是什么关系呢?对象又是什么时候释放的?

App启动后,苹果在主线程 RunLoop 里注册了两个 Observer,其回调都是 _wrapRunLoopWithAutoreleasePoolHandler()。

第一个 Observer 监视的事件是 Entry(即将进入Loop),其回调内会调用 _objc_autoreleasePoolPush() 创建自动释放池。其 order 是-2147483647,优先级最高,保证创建释放池发生在其他所有回调之前。

第二个 Observer 监视了两个事件:BeforeWaiting(准备进入休眠) 时调用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 释放旧的池并创建新池;Exit(即将退出Loop) 时调用 _objc_autoreleasePoolPop() 来释放自动释放池。这个 Observer 的 order 是 2147483647,优先级最低,保证其释放池子发生在其他所有回调之后。

在主线程执行的代码,通常是写在诸如事件回调、Timer回调内的。这些回调会被 RunLoop 创建好的 AutoreleasePool 环绕着,所以不会出现内存泄漏,开发者也不必显示创建 Pool 了。

验证结果:

2)手动autoreleasePool
我们可以通过@autoreleasepool {}方式手动创建autoreleasepool对象,那么这个对象什么时候释放呢?答案是除了autoreleasepool的大括号就释放了,我们可以看下下面的实验结果

从上面1、2、3的结果可以看出,当对象出了autoreleasepool的大括号就释放了。

另附上一份各好友收集的大厂面试题,需要iOS开发学习资料、面试真题,可以添加iOS开发进阶交流群,进群可自行下载!

iOS使用频率最高的内存管理有哪几种

1.释放时机
在dealloc的时候,会将weak属性的值设置为nil

2.如何实现
Runtime维护了一个weak表,用于存储指向某个对象的所有weak指针,对于 weak 对象会放入一个 hash 表中,Key是所指对象的地址,Value是weak指针的地址(这个地址的值是所指对象的地址)数组。 当此对象的引用计数为0的时候会 dealloc,假如 weak 指向的对象内存地址是a,那么就会以a为键, 在这个 weak 表中搜索,找到所有以a为键的 weak 对象,从而设置为 nil。
注:由于可能多个weak指针指向同一个对象,所以value为一个数组

weak 的实现原理可以概括以下三步:

1)初始化时:runtime会调用objc_initWeak函数,初始化一个新的weak指针指向对象的地址。
我们以下面这行代码为例:

代码清单1:示例代码

当我们初始化一个weak变量时,runtime会调用objc_initWeak函数。这个函数在Clang中的声明如下:

其具体实现如下:

示例代码轮换成编译器的模拟代码如下:

因此,这里所做的事是先将obj1初始化为0(nil),然后将obj1的地址及obj作为参数传递给objc_storeWeak函数。
objc_initWeak函数有一个前提条件:就是object必须是一个没有被注册为__weak对象的有效指针。而value则可以是null,或者指向一个有效的对象。

2)添加引用时:objc_initWeak函数会调用 objc_storeWeak() 函数。
objc_storeWeak() 的作用是更新指针指向,创建对应的弱引用表。

3)释放时,调用clearDeallocating函数。
clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从weak表中删除,最后清理对象的记录。

NSString内存分为两种类型:

__NSCFConstantString(常量区)

__NSCFString(堆区)、NSTaggedPointerString(堆区)

生成一个NSString类型的字符串有三种方法:

方法1.直接赋值:

方法2.类函数初始化生成:

方法3.实例方法初始化生成:

1)对于__NSCFConstantString
这种类型的字符串是常量字符串。该类型的字符串以字面量的方式创建,保存在字符串常量区,是在编译时创建的。

2)对于__NSCFStringNSTaggedPointerString

__NSCFString 表示对象类型的字符串,在运行时创建,保存在堆区,初始引用计数为1,其内存管理方式就是对象的内存管理方式。

NSTaggedPointerString是对__NSCFString类型的一种优化,在运行创建字符串时,会对字符串内容及长度作判断,若内容由ASCII字符构成且长度较小(具体要多小暂时不太清楚),这时候创建的字符串类型就是 NSTaggedPointerString

对于不可以变NSString的测试结果:

对于可变的NSMutableString

从结果我们可以看出来NSMutableString都是分配在堆区,且是__NSCFString类型,NSString中Format相关方法也是都分配在堆区,但是会根据字符串的长度,区分为__NSCFString和NSTaggedPointerString两种。在分配堆区的这些变量,其实一部分是正常的对象,一部分变成autorelease对象,具体是哪些,我们可以使用_objc_autoreleasePoolPrint()打印出来,比如实例中的g、ms4、ms5、ms6。

本文:iOS使用频率最高的内存管理有哪几种的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:怎么理解iOS开发中的锁下一篇:

14 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18