Function objc2::rc::autoreleasepool
source · pub fn autoreleasepool<T, F>(f: F) -> Twhere
for<'p> F: FnOnce(&'p AutoreleasePool) -> T + AutoreleaseSafe,
Expand 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.
The pool is passed as a reference to the enclosing function to give it a lifetime parameter that autoreleased objects can refer to.
The given reference must not be used in an inner autoreleasepool
,
doing so will panic with debug assertions enabled, and be a compile
error in a future release. You can test the compile error with the
unstable-autoreleasesafe
crate feature on nightly Rust.
Note that this is mostly useful for preventing leaks (as any Objective-C
method may leak internally). If implementing an interface to an object,
you should try to return retained pointers with msg_send_id!
wherever
you can instead, since having to use this function can be quite cumbersome
for your users!
Examples
Basic usage:
use core::mem::ManuallyDrop;
use objc2::{class, msg_send, msg_send_id};
use objc2::rc::{autoreleasepool, AutoreleasePool, Id, Owned};
use objc2::runtime::Object;
fn needs_lifetime_from_pool<'p>(pool: &'p AutoreleasePool) -> &'p mut Object {
let obj: Id<Object, Owned> = unsafe { msg_send_id![class!(NSObject), new] };
let obj = ManuallyDrop::new(obj);
let obj: *mut Object = unsafe { msg_send![obj, autorelease] };
// Lifetime of the returned reference is bounded by the pool
unsafe { pool.ptr_as_mut(obj) }
// Or simply
// let obj: Id<Object, Owned> = unsafe { msg_send_id![class!(NSObject), new] };
// obj.autorelease(pool)
}
autoreleasepool(|pool| {
// Create `obj` and autorelease it to the pool
let obj = needs_lifetime_from_pool(pool);
// ... use `obj` here
// `obj` is deallocated when the pool ends
});
Fails to compile because obj
does not live long enough for us to
safely take it out of the pool:
let obj = autoreleasepool(|pool| {
let obj = needs_lifetime_from_pool(pool);
// Use `obj`
obj
});
Incorrect usage which panics (with debug assertions enabled) because we tried to pass an outer pool to an inner pool:
autoreleasepool(|outer_pool| {
let obj = autoreleasepool(|inner_pool| {
let obj = needs_lifetime_from_pool(outer_pool);
obj
});
// `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.
});