美文网首页iOS 收藏篇
RunLoop 与 AutoreleasePool 的关系

RunLoop 与 AutoreleasePool 的关系

作者: iVikings | 来源:发表于2020-05-08 11:39 被阅读0次

程序启动后,苹果在主线程 RunLoop 里注册了2个 Observer

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

  • 第2个 Observer 监听了两个事件:kCFRunLoopBeforeWaiting(准备进入休眠) 和 kCFRunLoopExit(即将退出Loop),其 order = 2147483647,优先级最低,保证其释放池子发生在其他所有回调之后。

  • kCFRunLoopBeforeWaiting(准备进入休眠)时,会调用 _objc_autoreleasePoolPop()_objc_autoreleasePoolPush 释放旧的池并创建新池;
  • kCFRunLoopExit(即将退出Loop)时,会调用 _objc_autoreleasePoolPop() 来释放自动释放池。

在程序中断点调试 (lldb) : po [NSRunLoop mainRunLoop] 可以看到 MainRunLoopCommon mode Items 中就有这两个 Observer

observers = (
    "<CFRunLoopObserver 0x60000155c140 [0x7fff8062ce40]>{valid = Yes, activities = 0x1, repeats = Yes, order = -2147483647, callout = _wrapRunLoopWithAutoreleasePoolHandler (0x7fff48bc10bc), context = <CFArray 0x600002a6e4c0 [0x7fff8062ce40]>{type = mutable-small, count = 1, values = (\n\t0 : <0x7fc9b880b048>\n)}}",
    "<CFRunLoopObserver 0x6000015580a0 [0x7fff8062ce40]>{valid = Yes, activities = 0x20, repeats = Yes, order = 0, callout = _UIGestureRecognizerUpdateObserver (0x7fff4874f06a), context = <CFRunLoopObserver context 0x600000f59030>}",
    "<CFRunLoopObserver 0x60000155c000 [0x7fff8062ce40]>{valid = Yes, activities = 0xa0, repeats = Yes, order = 1999000, callout = _beforeCACommitHandler (0x7fff48bf1fb7), context = <CFRunLoopObserver context 0x7fc9b8605030>}",
    "<CFRunLoopObserver 0x600001558640 [0x7fff8062ce40]>{valid = Yes, activities = 0xa0, repeats = Yes, order = 2000000, callout = _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv (0x7fff2b43cfa2), context = <CFRunLoopObserver context 0x0>}",
    "<CFRunLoopObserver 0x60000155c0a0 [0x7fff8062ce40]>{valid = Yes, activities = 0xa0, repeats = Yes, order = 2001000, callout = _afterCACommitHandler (0x7fff48bf2020), context = <CFRunLoopObserver context 0x7fc9b8605030>}",
    "<CFRunLoopObserver 0x60000155c1e0 [0x7fff8062ce40]>{valid = Yes, activities = 0xa0, repeats = Yes, order = 2147483647, callout = _wrapRunLoopWithAutoreleasePoolHandler (0x7fff48bc10bc), context = <CFArray 0x600002a6e4c0 [0x7fff8062ce40]>{type = mutable-small, count = 1, values = (\n\t0 : <0x7fc9b880b048>\n)}}"
)

根据 Run Loop Observer Activities 枚举值:

/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    kCFRunLoopEntry = (1UL << 0),          // 即将进入Loop
    kCFRunLoopBeforeTimers = (1UL << 1),   // 即将处理 Timer
    kCFRunLoopBeforeSources = (1UL << 2),  // 即将处理 Source
    kCFRunLoopBeforeWaiting = (1UL << 5),  // 即将进入休眠
    kCFRunLoopAfterWaiting = (1UL << 6),   // 刚从休眠中唤醒
    kCFRunLoopExit = (1UL << 7),           // 即将退出 Loop
    kCFRunLoopAllActivities = 0x0FFFFFFFU  // 包含上面所有状态
};

activities = 0x1 :对应 kCFRunLoopEntry
activities = 0xa0:对应 kCFRunLoopBeforeWaiting | kCFRunLoopExit

通过以上分析可知:系统在每个 RunLoop 迭代循环中都加入了 自动释放池 Push 和 PopAutorelease对象 会在当前的RunLoop 迭代循环结束时 释放


相关文章

网友评论

    本文标题:RunLoop 与 AutoreleasePool 的关系

    本文链接:https://www.haomeiwen.com/subject/mngxnhtx.html