It’s not uncommon for an interviewer to ask this question in an interview. When was AutoreleasePool destroyed? To answer this question, you must know something about AutoreleasePool and RunLoop.
When was AutoreleasePool created, and when was it destroyed? Here’s a quick review of what AutoreleasePool does. AutoreleasePool is called an autorelease pool, in which objects that call the AutoRelease method are pushed to the top of the pool (managing objects as a stack). When the auto-release pool is destroyed, objects in the pool automatically call the release method to release resources and destroy objects. To achieve the purpose of automatic memory management. We rarely actively create AutoreleasePool objects in development. Why is that? What about using it to automatically manage memory? The system created the AutoreleasePool object for us at runtime, but we didn’t know it. So when was it created? Take a look at the official source:
CFRunLoop {
current mode = kCFRunLoopDefaultMode
common modes = {
UITrackingRunLoopMode
kCFRunLoopDefaultMode }
common mode items = {
// source0 (manual)
CFRunLoopSource {order =-1, {
callout = _UIApplicationHandleEventQueue}}
CFRunLoopSource {order =-1, {
callout = PurpleEventSignalCallback }}
CFRunLoopSource {order = 0, {
callout = FBSSerialQueueRunLoopSourceHandler}}
// source1 (mach port) CFRunLoopSource {order = 0, {port = 17923}} CFRunLoopSource {order = 0, {port = 12039}} CFRunLoopSource {order = 0, {port = 16647}} CFRunLoopSource {order =-1, { callout = PurpleEventCallback}} CFRunLoopSource {order = 0, {port = 2407, callout = _ZL20notify_port_callbackP12__CFMachPortPvlS1_}} CFRunLoopSource {order = 0, {port = 1c03, callout = __IOHIDEventSystemClientAvailabilityCallback}} CFRunLoopSource {order = 0, {port = 1b03, callout = __IOHIDEventSystemClientQueueCallback}} CFRunLoopSource {order = 1, {port = 1903, The callout = __IOMIGMachPortPortCallback}} / / Ovserver / / pay attention here / / Entry into CFRunLoopObserver {order = - 2147483647, activities = 0x1, callout = _wrapRunLoopWithAutoreleasePoolHandler} // BeforeWaiting CFRunLoopObserver {order = 0, activities = 0x20, callout = _UIGestureRecognizerUpdateObserver} // BeforeWaiting | Exit CFRunLoopObserver {order = 1999000, activities = 0xa0, callout = _afterCACommitHandler} // BeforeWaiting | Exit CFRunLoopObserver {order = 2000000, activities = 0xa0, The callout = _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv} / / BeforeWaiting | Exit into dormancy or Exit / / attention here The lowest priority, CFRunLoopObserver {order = 2147483647, Activities = 0xA0, The callout = _wrapRunLoopWithAutoreleasePoolHandler} / / Timer CFRunLoopTimer {firing = No, interval = 3.1536 e+09, Tolerance = 0, next fire date = 453098071 (-4421.76019@96223387169499), callout = _ZN2CAL14timer_callbackEP16__CFRunLoopTimerPv (QuartzCore.framework)} }, Modes = {CFRunLoopMode {sources0 = {/* same as'common mode items' */ },
sources1 = { /* same as 'common mode items' */ },
observers = { /* same as 'common mode items' */ },
timers = { /* same as 'common mode items' */ },
},
CFRunLoopMode {
sources0 = { /* same as 'common mode items' */ },
sources1 = { /* same as 'common mode items' */ },
observers = { /* same as 'common mode items' */ },
timers = { /* same as 'common mode items' */ },
},
CFRunLoopMode {
sources0 = {
CFRunLoopSource {order = 0, {
callout = FBSSerialQueueRunLoopSourceHandler}}
},
sources1 = (null),
observers = {
CFRunLoopObserver >{activities = 0xa0, order = 2000000,
callout = _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv}
)},
timers = (null),
},
CFRunLoopMode {
sources0 = {
CFRunLoopSource {order = -1, {
callout = PurpleEventSignalCallback}}
},
sources1 = {
CFRunLoopSource {order = -1, {
callout = PurpleEventCallback}}
},
observers = (null),
timers = (null),
},
CFRunLoopMode {
sources0 = (null),
sources1 = (null),
observers = (null),
timers = (null),
}
}
}
Copy the code
The App starts, the system in the main thread RunLoop registered two Observser, the callback is _wrapRunLoopWithAutoreleasePoolHandler ().
The first Observer monitors an event called Entry(about to enter Loop), which creates an automatic release pool within its callback by calling _objc_autoreleasePoolPush(). It has the highest priority and ensures that the release pool is created before all other callbacks.
The second Observer monitors two events
-
_BeforeWaiting(ready to sleep) _ calls _objc_autoreleasePoolPop() and _objc_autoreleasePoolPush() torelease old pools and create new ones;
-
_Exit(about to exit Loop) _ calls _objc_autoreleasePoolPop() torelease the automatic release pool. This Observer has the lowest priority and ensures that its release pool occurs after all other callbacks.
The code that executes on the main thread is usually written inside such callbacks as event callbacks and Timer callbacks. These callbacks are surrounded by AutoreleasePool created by RunLoop, so there is no memory leak and the developer does not have to show that the Pool was created.
We now know that AutoreleasePool is created and destroyed when RunLoop is about to enter the RunLoop state and when RunLoop is about to enter sleep state.
So AutoreleasePool can be released in one of two ways. One is that the Autorelease object is released at the end of the current runloop iteration, and it can be released because the system adds automatic release pools of Push and Pop to each runloop iteration. The second method is to manually destroy AutoreleasePool by calling its drain method