pub struct Retained<T: ?Sized> { /* private fields */ }
Expand description
A reference counted pointer type for Objective-C objects.
Retained
strongly references or “retains” the given object T
, and
decrements the retain count or “releases” it again when dropped, thereby
ensuring it will be deallocated at the right time.
The type T
inside Retained<T>
can be anything that implements
Message
.
This can usually be gotten from one of the methods in the framework
crates, but can also be created manually with the msg_send!
macro, or
even more manually with the Retained::retain
, Retained::from_raw
and Retained::retain_autoreleased
methods.
§Comparison to std
types
Retained<T>
is the Objective-C equivalent of Arc
, that is, it is a
thread-safe reference-counting pointer, and allows cloning by bumping the
reference count, and weak references using rc::Weak
.
Unlike Arc
, objects can be retained directly from a &T
using
Message::retain
(for Arc
you need &Arc<T>
).
Even though most Objective-C types aren’t thread safe, Objective-C has no
concept of Rc
. Retain/release operations are always atomic.
§Forwarding implementations
Since Retained<T>
is a smart pointer, it Deref
s to T
.
It also forwards the implementation of a bunch of standard library traits
such as PartialEq
, AsRef
, and so on, so that it becomes possible
to use e.g. Retained<NSString>
as if it was NSString
. Note that having
NSString
directly is not possible since Objective-C objects cannot live
on the stack, but instead must reside on the heap, and as such must be
accessed behind a pointer or a reference (i.e. &NSString
).
Note that because of current limitations in the Rust trait system, some
traits like Default
, IntoIterator
, FromIterator
, From
and
Into
are not directly implementable on NSString
; for that use-case,
we instead provide the DefaultRetained
, RetainedIntoIterator
and
RetainedFromIterator
traits, which make some of the the aforementioned
traits implementable on Retained
.
§Memory layout
This is guaranteed to have the same size and alignment as a pointer to the
object, *const T
.
Additionally, it participates in the null-pointer optimization, that is,
Option<Retained<T>>
is guaranteed to have the same size as
Retained<T>
.
§Example
Various usage of Retained
on an immutable object.
use objc2_foundation::{NSObject, NSString};
use objc2::rc::Retained;
use objc2::{ClassType, msg_send};
// Use `msg_send!` to create an `Retained` with correct memory management
//
// SAFETY: The types are correct, and it is safe to call the `new`
// selector on `NSString`.
let string: Retained<NSString> = unsafe { msg_send![NSString::class(), new] };
// Or:
// let string = NSString::new();
// Methods on `NSString` is usable via `Deref`
assert_eq!(string.length(), 0);
// Bump the reference count of the object.
let another_ref: Retained<NSString> = string.clone();
// Convert one of the references to a reference to `NSObject` instead
let obj: Retained<NSObject> = string.into_super();
// And use the `Debug` impl from that
assert_eq!(format!("{obj:?}"), "");
// Finally, the `Retained`s go out of scope, the reference counts are
// decreased, and the string will deallocate
Implementations§
Source§impl<T: ?Sized + Message> Retained<T>
impl<T: ?Sized + Message> Retained<T>
Sourcepub unsafe fn from_raw(ptr: *mut T) -> Option<Self>
pub unsafe fn from_raw(ptr: *mut T) -> Option<Self>
Construct an Retained
from a pointer that already has +1 retain count.
Returns None
if the pointer was NULL.
This is useful when you have a retain count that has been handed off
from somewhere else, usually Objective-C methods like init
, alloc
,
new
, copy
, or methods with the ns_returns_retained
attribute.
If you do not have +1 retain count, such as if your object was
retrieved from other methods than the ones noted above, use
Retained::retain
instead.
§Safety
You must uphold the same requirements as described in Retained::retain
.
Additionally, you must ensure the given object pointer has +1 retain count.
§Example
Comparing different ways of creating a new NSObject
.
use objc2::rc::Retained;
use objc2::runtime::NSObject;
use objc2::{msg_send, AnyThread, ClassType};
// Manually using `msg_send!`, pointers and `Retained::from_raw`
let obj: *mut NSObject = unsafe { msg_send![NSObject::class(), alloc] };
let obj: *mut NSObject = unsafe { msg_send![obj, init] };
// SAFETY: `-[NSObject init]` returns +1 retain count
let obj: Retained<NSObject> = unsafe { Retained::from_raw(obj).unwrap() };
// Or automatically by specifying `Retained` as the return value from
// `msg_send!` (it will do the correct conversion internally).
let obj: Retained<NSObject> = unsafe { msg_send![NSObject::alloc(), init] };
// Or using the `NSObject::new` method
let obj = NSObject::new();
Sourcepub unsafe fn new(ptr: *mut T) -> Option<Self>
👎Deprecated: use the more descriptive name Retained::from_raw
instead
pub unsafe fn new(ptr: *mut T) -> Option<Self>
Retained::from_raw
insteadSourcepub fn into_raw(this: Self) -> *mut T
pub fn into_raw(this: Self) -> *mut T
Consumes the Retained
, returning a raw pointer with +1 retain count.
After calling this function, the caller is responsible for the memory
previously managed by the Retained
.
This is effectively the opposite of Retained::from_raw
, see that for
more details on when this function is useful.
§Examples
Converting an Retained
to a pointer and back.
use objc2::rc::Retained;
use objc2::runtime::NSObject;
let obj = NSObject::new();
let ptr = Retained::into_raw(obj);
// SAFETY: The pointer is valid, and has +1 retain count from above.
let obj = unsafe { Retained::from_raw(ptr) }.unwrap();
Source§impl<T: Message> Retained<T>
impl<T: Message> Retained<T>
Sourcepub fn downcast<U: DowncastTarget>(self) -> Result<Retained<U>, Retained<T>>where
Self: 'static,
pub fn downcast<U: DowncastTarget>(self) -> Result<Retained<U>, Retained<T>>where
Self: 'static,
Attempt to downcast the object to a class of type U
.
See AnyObject::downcast_ref
for more details.
§Errors
If casting failed, this will return the object back as the Err
type. If you do not care about this, and just want an Option
, use
.downcast().ok()
.
§Example
Cast a string to an object, and back again.
use objc2_foundation::{NSString, NSObject};
let string = NSString::new();
// The string is an object
let obj = string.downcast::<NSObject>().unwrap();
// And it is also a string
let string = obj.downcast::<NSString>().unwrap();
Try to cast an object to a string, which will fail and return the
object in Err
.
use objc2_foundation::{NSString, NSObject};
let obj = NSObject::new();
let obj = obj.downcast::<NSString>().unwrap_err();
Sourcepub unsafe fn cast_unchecked<U: Message>(this: Self) -> Retained<U> ⓘ
pub unsafe fn cast_unchecked<U: Message>(this: Self) -> Retained<U> ⓘ
Convert the type of the given object to another.
This is equivalent to a cast
between two pointers.
See Retained::into_super
, ProtocolObject::from_retained
and
Retained::downcast
for safe alternatives.
This is common to do when you know that an object is a subclass of
a specific class (e.g. casting an instance of NSString
to NSObject
is safe because NSString
is a subclass of NSObject
), but do not
want to pay the (very slight) performance price of dynamically
checking that precondition with a downcast
.
All 'static
objects can safely be cast to AnyObject
, since that
assumes no specific class.
This is an associated method, and must be called as
Retained::cast_unchecked(obj)
.
§Safety
You must ensure that the object can be reinterpreted as the given type.
If T
is not 'static
, you must ensure that U
ensures that the
data contained by T
is kept alive for as long as U
lives.
Additionally, you must ensure that any safety invariants that the new type has are upheld.
Sourcepub unsafe fn cast<U: Message>(this: Self) -> Retained<U> ⓘ
👎Deprecated: Use downcast
, or cast_unchecked
instead
pub unsafe fn cast<U: Message>(this: Self) -> Retained<U> ⓘ
downcast
, or cast_unchecked
insteadSourcepub unsafe fn retain(ptr: *mut T) -> Option<Retained<T>>
pub unsafe fn retain(ptr: *mut T) -> Option<Retained<T>>
Retain the pointer and construct an Retained
from it.
Returns None
if the pointer was NULL.
This is useful when you have been given a pointer to an object from some API, and you would like to ensure that the object stays around while you work on it.
For normal Objective-C methods, you may want to use
Retained::retain_autoreleased
instead, as that is usually more
performant.
See also Message::retain
for a safe alternative where you already
have a reference to the object.
§Safety
The pointer must be valid as a reference (aligned, dereferenceable and
initialized, see the std::ptr
module for more information), or
NULL.
You must ensure that any data that T
may reference lives for at
least as long as T
.
Sourcepub unsafe fn retain_autoreleased(ptr: *mut T) -> Option<Retained<T>>
pub unsafe fn retain_autoreleased(ptr: *mut T) -> Option<Retained<T>>
Retains a previously autoreleased object pointer.
This is useful when calling Objective-C methods that return autoreleased objects, see Cocoa’s Memory Management Policy.
This has exactly the same semantics as Retained::retain
, except it can
sometimes avoid putting the object into the autorelease pool, possibly
yielding increased speed and reducing memory pressure.
Note: This relies heavily on being inlined right after msg_send!
,
be careful to not accidentally require instructions between these.
§Safety
Same as Retained::retain
.
Sourcepub fn autorelease_ptr(this: Self) -> *mut T
pub fn autorelease_ptr(this: Self) -> *mut T
Autoreleases the Retained
, returning a pointer.
The object is not immediately released, but will be when the innermost / current autorelease pool is drained.
This is useful when defining your own classes and you have some error
parameter passed as Option<&mut *mut NSError>
, and you want to
create and autorelease an error before returning.
This is an associated method, and must be called as
Retained::autorelease_ptr(obj)
.
§Safety
This method is safe to call, but the returned pointer is only guaranteed to be valid until the innermost autorelease pool is drained.
Sourcepub unsafe fn autorelease<'p>(this: Self, pool: AutoreleasePool<'p>) -> &'p T
pub unsafe fn autorelease<'p>(this: Self, pool: AutoreleasePool<'p>) -> &'p T
Autoreleases the Retained
, returning a reference bound to the pool.
The object is not immediately released, but will be when the innermost / current autorelease pool (given as a parameter) is drained.
This is an associated method, and must be called as
Retained::autorelease(obj, pool)
.
§Safety
The given pool must represent the innermost pool, to ensure that the reference is not moved outside the autorelease pool into which it has been put in.
Sourcepub fn autorelease_return(this: Self) -> *mut T
pub fn autorelease_return(this: Self) -> *mut T
Autoreleases and prepares the Retained
to be returned to Objective-C.
The object is not immediately released, but will be when the innermost autorelease pool is drained.
This is useful when defining your own methods where you will often find yourself in need of returning autoreleased objects to properly follow Cocoa’s Memory Management Policy.
To that end, you could also use Retained::autorelease_ptr
, but
this is more efficient than a normal autorelease
, since it makes a
best effort attempt to hand off ownership of the retain count to a
subsequent call to objc_retainAutoreleasedReturnValue
/
Retained::retain_autoreleased
in the enclosing call frame.
This optimization relies heavily on this function being tail called, so make sure you only call this function at the end of your method.
§Example
Returning an Retained
from a custom method (note: the
define_class!
macro supports doing this for you automatically).
use objc2::{class, msg_send, sel};
use objc2::rc::Retained;
use objc2::runtime::{AnyClass, AnyObject, ClassBuilder, Sel};
let mut builder = ClassBuilder::new(c"ExampleObject", class!(NSObject)).unwrap();
extern "C-unwind" fn get(cls: &AnyClass, _cmd: Sel) -> *mut AnyObject {
let obj: Retained<AnyObject> = unsafe { msg_send![cls, new] };
Retained::autorelease_return(obj)
}
unsafe {
builder.add_class_method(
sel!(get),
get as extern "C-unwind" fn(_, _) -> _,
);
}
let cls = builder.register();
Trait Implementations§
Source§impl<T: Message> Clone for Retained<T>
impl<T: Message> Clone for Retained<T>
Source§fn clone(&self) -> Self
fn clone(&self) -> Self
Retain the object, increasing its reference count.
This is equivalent to Message::retain
.
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moreSource§impl<T: ?Sized> Drop for Retained<T>
#[may_dangle]
(see this) doesn’t apply here since we
don’t run T
’s destructor (rather, we want to discourage having T
s with
a destructor); and even if we did run the destructor, it would not be safe
to add since we cannot verify that a dealloc
method doesn’t access
borrowed data.
impl<T: ?Sized> Drop for Retained<T>
#[may_dangle]
(see this) doesn’t apply here since we
don’t run T
’s destructor (rather, we want to discourage having T
s with
a destructor); and even if we did run the destructor, it would not be safe
to add since we cannot verify that a dealloc
method doesn’t access
borrowed data.
Source§impl<T: ?Sized + Error> Error for Retained<T>
Available on crate feature std
only.
impl<T: ?Sized + Error> Error for Retained<T>
std
only.Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
Source§impl<'a, A, T: ?Sized> Extend<A> for &'a Retained<T>
impl<'a, A, T: ?Sized> Extend<A> for &'a Retained<T>
Source§fn extend<I: IntoIterator<Item = A>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = A>>(&mut self, iter: I)
Source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one
)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one
)Source§impl<A, T: ?Sized> Extend<A> for Retained<T>
impl<A, T: ?Sized> Extend<A> for Retained<T>
Source§fn extend<I: IntoIterator<Item = A>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = A>>(&mut self, iter: I)
Source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one
)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one
)Source§impl<P: ?Sized + 'static> From<Retained<ProtocolObject<P>>> for Retained<AnyObject>
impl<P: ?Sized + 'static> From<Retained<ProtocolObject<P>>> for Retained<AnyObject>
Source§fn from(obj: Retained<ProtocolObject<P>>) -> Self
fn from(obj: Retained<ProtocolObject<P>>) -> Self
Convert the protocol object to AnyObject
.
Source§impl<T, U: RetainedFromIterator<T>> FromIterator<T> for Retained<U>
impl<T, U: RetainedFromIterator<T>> FromIterator<T> for Retained<U>
Source§fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self
Source§impl<'a, T: ?Sized> Hasher for &'a Retained<T>
impl<'a, T: ?Sized> Hasher for &'a Retained<T>
Source§fn write_u128(&mut self, i: u128)
fn write_u128(&mut self, i: u128)
u128
into this hasher.Source§fn write_usize(&mut self, i: usize)
fn write_usize(&mut self, i: usize)
usize
into this hasher.Source§fn write_i128(&mut self, i: i128)
fn write_i128(&mut self, i: i128)
i128
into this hasher.Source§fn write_isize(&mut self, i: isize)
fn write_isize(&mut self, i: isize)
isize
into this hasher.Source§fn write_length_prefix(&mut self, len: usize)
fn write_length_prefix(&mut self, len: usize)
hasher_prefixfree_extras
)Source§impl<T: ?Sized> Hasher for Retained<T>
impl<T: ?Sized> Hasher for Retained<T>
Source§fn write_u128(&mut self, i: u128)
fn write_u128(&mut self, i: u128)
u128
into this hasher.Source§fn write_usize(&mut self, i: usize)
fn write_usize(&mut self, i: usize)
usize
into this hasher.Source§fn write_i128(&mut self, i: i128)
fn write_i128(&mut self, i: i128)
i128
into this hasher.Source§fn write_isize(&mut self, i: isize)
fn write_isize(&mut self, i: isize)
isize
into this hasher.Source§fn write_length_prefix(&mut self, len: usize)
fn write_length_prefix(&mut self, len: usize)
hasher_prefixfree_extras
)Source§impl<'a, T: ?Sized> IntoIterator for &'a Retained<T>where
&'a T: IntoIterator,
impl<'a, T: ?Sized> IntoIterator for &'a Retained<T>where
&'a T: IntoIterator,
Source§impl<T: ?Sized + RetainedIntoIterator> IntoIterator for Retained<T>
impl<T: ?Sized + RetainedIntoIterator> IntoIterator for Retained<T>
Source§impl<T: Ord + ?Sized> Ord for Retained<T>
impl<T: Ord + ?Sized> Ord for Retained<T>
Source§impl<T: ?Sized + PartialOrd<U>, U: ?Sized> PartialOrd<Retained<U>> for Retained<T>
impl<T: ?Sized + PartialOrd<U>, U: ?Sized> PartialOrd<Retained<U>> for Retained<T>
Source§impl<'a, T: ?Sized> Read for &'a Retained<T>
Available on crate feature std
only.
impl<'a, T: ?Sized> Read for &'a Retained<T>
std
only.Source§fn read(&mut self, buf: &mut [u8]) -> Result<usize>
fn read(&mut self, buf: &mut [u8]) -> Result<usize>
Source§fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
read
, except that it reads into a slice of buffers. Read moreSource§fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize>
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize>
buf
. Read moreSource§fn read_to_string(&mut self, buf: &mut String) -> Result<usize>
fn read_to_string(&mut self, buf: &mut String) -> Result<usize>
buf
. Read moreSource§fn read_exact(&mut self, buf: &mut [u8]) -> Result<()>
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()>
buf
. Read moreSource§fn is_read_vectored(&self) -> bool
fn is_read_vectored(&self) -> bool
can_vector
)Source§fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<(), Error>
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<(), Error>
read_buf
)Source§fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>
fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>
read_buf
)cursor
. Read more1.0.0 · Source§fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
Read
. Read moreSource§impl<T: ?Sized> Read for Retained<T>
Available on crate feature std
only.
impl<T: ?Sized> Read for Retained<T>
std
only.Source§fn read(&mut self, buf: &mut [u8]) -> Result<usize>
fn read(&mut self, buf: &mut [u8]) -> Result<usize>
Source§fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>
read
, except that it reads into a slice of buffers. Read moreSource§fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize>
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize>
buf
. Read moreSource§fn read_to_string(&mut self, buf: &mut String) -> Result<usize>
fn read_to_string(&mut self, buf: &mut String) -> Result<usize>
buf
. Read moreSource§fn read_exact(&mut self, buf: &mut [u8]) -> Result<()>
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()>
buf
. Read moreSource§fn is_read_vectored(&self) -> bool
fn is_read_vectored(&self) -> bool
can_vector
)Source§fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<(), Error>
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<(), Error>
read_buf
)Source§fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>
fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>
read_buf
)cursor
. Read more1.0.0 · Source§fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
Read
. Read moreSource§impl<'a, T: ?Sized> Seek for &'a Retained<T>
Available on crate feature std
only.
impl<'a, T: ?Sized> Seek for &'a Retained<T>
std
only.Source§fn seek(&mut self, pos: SeekFrom) -> Result<u64>
fn seek(&mut self, pos: SeekFrom) -> Result<u64>
Source§fn stream_position(&mut self) -> Result<u64>
fn stream_position(&mut self) -> Result<u64>
1.55.0 · Source§fn rewind(&mut self) -> Result<(), Error>
fn rewind(&mut self) -> Result<(), Error>
Source§impl<T: ?Sized> Seek for Retained<T>
Available on crate feature std
only.
impl<T: ?Sized> Seek for Retained<T>
std
only.Source§fn seek(&mut self, pos: SeekFrom) -> Result<u64>
fn seek(&mut self, pos: SeekFrom) -> Result<u64>
Source§fn stream_position(&mut self) -> Result<u64>
fn stream_position(&mut self) -> Result<u64>
1.55.0 · Source§fn rewind(&mut self) -> Result<(), Error>
fn rewind(&mut self) -> Result<(), Error>
Source§impl<'a, T: ?Sized> Write for &'a Retained<T>
impl<'a, T: ?Sized> Write for &'a Retained<T>
Source§impl<'a, T: ?Sized> Write for &'a Retained<T>
Available on crate feature std
only.
impl<'a, T: ?Sized> Write for &'a Retained<T>
std
only.Source§fn write(&mut self, buf: &[u8]) -> Result<usize>
fn write(&mut self, buf: &[u8]) -> Result<usize>
Source§fn flush(&mut self) -> Result<()>
fn flush(&mut self) -> Result<()>
Source§fn write_all(&mut self, buf: &[u8]) -> Result<()>
fn write_all(&mut self, buf: &[u8]) -> Result<()>
Source§fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<()>
fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<()>
Source§fn is_write_vectored(&self) -> bool
fn is_write_vectored(&self) -> bool
can_vector
)Source§impl<T: ?Sized> Write for Retained<T>
Available on crate feature std
only.
impl<T: ?Sized> Write for Retained<T>
std
only.Source§fn write(&mut self, buf: &[u8]) -> Result<usize>
fn write(&mut self, buf: &[u8]) -> Result<usize>
Source§fn flush(&mut self) -> Result<()>
fn flush(&mut self) -> Result<()>
Source§fn write_all(&mut self, buf: &[u8]) -> Result<()>
fn write_all(&mut self, buf: &[u8]) -> Result<()>
Source§fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<()>
fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<()>
Source§fn is_write_vectored(&self) -> bool
fn is_write_vectored(&self) -> bool
can_vector
)impl<T: Eq + ?Sized> Eq for Retained<T>
impl<T: ?Sized + RefUnwindSafe> RefUnwindSafe for Retained<T>
impl<T: ?Sized + Sync + Send> Send for Retained<T>
Retained<T>
is Send
if T
is Send + Sync
.
impl<T: ?Sized + Sync + Send> Sync for Retained<T>
Retained<T>
is Sync
if T
is Send + Sync
.