pub fn autoreleasepool<T, F>(f: F) -> TExpand description
Execute f in the context of a new autorelease pool. The pool is drained
after the execution of f completes.
This corresponds to @autoreleasepool blocks in Objective-C and Swift,
see Apple’s documentation for general information on
when to use those.
The pool is passed as a parameter to the closure to give you a lifetime parameter that autoreleased objects can refer to.
Note that this is mostly useful for preventing leaks (as any Objective-C
method may autorelease internally - see also autoreleasepool_leaking).
If implementing an interface to an object, you should try to return
retained pointers with msg_send! wherever you can instead, since
it is usually more efficient, safer, and having to use this function can
be quite cumbersome for users.
§Restrictions
The given parameter must not be used inside a nested autoreleasepool,
since doing so will give the objects that it is used with an incorrect
lifetime bound.
You can try to enable the "unstable-autoreleasesafe" Cargo feature using
nightly Rust - if your use of this function compiles with that, it is more
likely to be correct, though note that Rust does not have a way to express
the lifetimes involved, so we cannot detect all invalid usage. See issue
#540 for details.
§Examples
Use an external API, and ensure that the memory that it used is cleaned up afterwards.
use objc2::rc::autoreleasepool;
use example_crate::example_function;
autoreleasepool(|_| {
// Call `example_function` in the context of a pool
example_function();
}); // Memory released into the pool is cleaned up when the scope endsAutorelease an object into an autorelease pool:
use objc2::rc::{autoreleasepool, Retained};
use objc2::runtime::NSObject;
autoreleasepool(|pool| {
// Create `obj` and autorelease it to the pool
// SAFETY: The pool is the current innermost pool
let obj = unsafe { Retained::autorelease(NSObject::new(), pool) };
// We now have a reference that we can freely use
println!("{obj:?}");
}); // `obj` is deallocated when the pool ends
// And is no longer usable outside the closureFails to compile because obj does not live long enough for us to take it
out of the pool:
use objc2::rc::{autoreleasepool, Retained};
use objc2::runtime::NSObject;
let obj = autoreleasepool(|pool| unsafe {
Retained::autorelease(NSObject::new(), pool)
});Fails to compile with the "unstable-autoreleasesafe" feature enabled, or
panics with debug assertions enabled, because we tried to pass an outer
pool to an inner pool:
use objc2::rc::{autoreleasepool, Retained};
use objc2::runtime::NSObject;
autoreleasepool(|outer_pool| {
let obj = autoreleasepool(|inner_pool| {
// SAFETY: NOT safe, the pool is _not_ the innermost pool!
unsafe { Retained::autorelease(NSObject::new(), outer_pool) }
});
// `obj` could wrongly be used here because its lifetime was
// assigned to the outer pool, even though it was released by the
// inner pool already.
});It is impossible to extend the lifetime of the pool.
use std::cell::RefCell;
use objc2::rc::{autoreleasepool, AutoreleasePool};
thread_local! {
static POOL: RefCell<Option<&'static AutoreleasePool<'static>>> = RefCell::new(None);
}
autoreleasepool(|pool| {
POOL.with(|p| {
*p.borrow_mut() = Some(Box::leak(Box::new(pool)))
});
});