内存管理

内存管理

计时不准问题

NSTimer依赖于RunLoop,如果RunLoop的任务过于繁重,可能会导致NSTimer不准时
解决:
1.添加到NSRunLoopCommonModes(注意这并不是一个真正的model)
2.可以使用GCD计时器(与Runloop没啥关系,直接调用内核函数)。

循环引用解决的第三方类:NSProxy

内存布局:


image.png

Tagged Pointer技术

从64bit开始,iOS引入了Tagged Pointer技术,用于优化NSNumber、NSDate、NSString等小对象的存储
使用Tagged Pointer之后,NSNumber指针里面存储的数据变成了:Tag + Data,也就是将数据直接存储在了指针中
判断是否是 Tagged Pointer 指针
iOS平台,最高有效位是1(第64bit)
Mac平台,最低有效位是1

Tagged Pointer之前 Tagged Pointer之后
number = 0x10001 number = 0xb000a1
地址:0x10001 NSNumber对象 存储值:10 存储值:10

dealloc

当一个对象要释放时,会自动调用dealloc,接下的调用轨迹是:
dealloc
_objc_rootDealloc
rootDealloc
object_dispose
objc_destructInstance、free

void *objc_destructInstance (id obj)
{
    if (obj) {
        // Read all of the flags at once for performance.
        bool cxx = obj-›hasCxxDtor() ;
        bool assoc = obj-›hasAssociatedobjects();
        // This order is important.
        if (cxx) object_cxxDestruct(obj);
        //清除成员变量
        if (assoc) obiect remove assocations (obi):
            obj->clearDeallocating();//将指向当前对象的弱指针置为ni1
    }
    return obj;
}

自动释放池

自动释放池的主要底层数据结构是:__AtAutoreleasePool、AutoreleasePoolPage
调用了autorelease的对象最终都是通过AutoreleasePoolPage对象来管理的
AutoreleasePoolPage对象:

class AutoreleasePoolPage
{
    magic_t const magic;
    id *next:
    thread_t const thread;
    AutoreleasePoolPage * cost parent;
    AutoreleasePoolPage*child;
    uint32 t const depth:
    uint32 t hiwat:
}
image.png

1.每一个AutoreleasePoolPage都有一个parent、child指针指向上一个和下一个.
2.id *next指向了下一个能存放autorelease对象地址的区域
3.调用push方法会将一个POOL_BOUNDARY(哨兵对象)入栈,并且返回其存放的内存地址
4.调用pop方法时传入一个POOL_BOUNDARY的内存地址,会从最后一个入栈的对象开始发送release消息,直到遇到这个POOL_BOUNDARY
5.POOL_BOUNDARY 就是哨兵对象,它是一个宏,值为nil,标志着一个自动释放池的边界。
6.autoreleasepoolpage 是以双向链表的形式连接起来的,只有新建一个pool会执行push操作,这时候会在page中插入一个POOL_BOUNDARY,并不是每页都插

main函数里面的Autorelease:
iOS在主线程的Runloop中注册了2个Observer
第1个Observer监听了kCFRunLoopEntry事件,会调用objc_autoreleasePoolPush()
第2个Observer
监听了kCFRunLoopBeforeWaiting事件,会调用objc_autoreleasePoolPop()、objc_autoreleasePoolPush()
监听了kCFRunLoopBeforeExit事件,会调用objc_autoreleasePoolPop()

你可能感兴趣的:(内存管理)