/// The root class of most Objective-C class hierarchies. /// /// This represents the [`NSObject` class][cls]. The name "NSObject" also /// refers to a protocol, see [`NSObjectProtocol`] for that. /// /// This class has been defined in `objc` since macOS 10.8, but is also /// re-exported under `objc2_foundation::NSObject`, you might want to use that /// path instead. /// /// [cls]: https://developer.apple.com/documentation/objectivec/nsobject?language=objc #[repr(C)] pubstruct NSObject {
__superclass: AnyObject,
}
// Would be _super_ nice to have this kind of impl, but that isn't possible. // impl Unsize<AnyObject> for NSObject {}
// We do not want to expose this type publicly, even though it's exposed in // the trait impl. mod private { #[derive(PartialEq, Eq, Hash)] // Delegate to NSObject pubstruct ForDefinedSubclasses(pub(super) super::NSObject);
}
// SAFETY: `NSObject` is thread safe by itself, the only reason why it // isn't marked `Send` is because its subclasses may not be thread safe. // // But any subclass of NSObject that the user creates is thread safe, provided // that their ivars are thread safe too, and the class is not configured as // `MainThreadOnly`. // // This special casing of NSObject is similar to what Swift does: // https://developer.apple.com/documentation/swift/sendable#Sendable-Classes unsafeimpl Send for private::ForDefinedSubclasses {} // SAFETY: Same as above. unsafeimpl Sync for private::ForDefinedSubclasses {}
// NSObject itself is also unwind safe, and so subclasses should be too, // unless they use e.g. interior mutability in their ivars. impl UnwindSafe for private::ForDefinedSubclasses {} impl RefUnwindSafe for private::ForDefinedSubclasses {}
unsafeimpl ClassType for NSObject { typeSuper = AnyObject; type ThreadKind = dyn AnyThread; const NAME: &'static str = "NSObject";
// Defined subclasses can assume more lenient auto traits. type __SubclassingType = private::ForDefinedSubclasses;
}
unsafeimpl DowncastTarget for NSObject {}
/// The methods that are fundamental to most Objective-C objects. /// /// This represents the [`NSObject` protocol][proto]. /// /// You should rarely need to use this for anything other than as a trait /// bound in [`extern_protocol!`], to allow your protocol to implement `Debug` /// `Hash`, `PartialEq` and `Eq`. /// /// This trait is exported under `objc2_foundation::NSObjectProtocol`, you /// probably want to use that path instead. /// /// [proto]: https://developer.apple.com/documentation/objectivec/1418956-nsobject?language=objc /// [`extern_protocol!`]: crate::extern_protocol! /// /// /// # Safety /// /// Like with [other protocols](ProtocolType), the type must represent a class /// that implements the `NSObject` protocol. #[allow(non_snake_case)] // Follow the naming scheme in framework crates pubunsafetrait NSObjectProtocol { /// Check whether the object is equal to an arbitrary other object. /// /// Most objects that implement `NSObjectProtocol` also implements the /// [`PartialEq`] trait. If the objects you are comparing are of the same /// type, you likely want to use that instead. /// /// See [Apple's documentation][apple-doc] for details. /// /// [apple-doc]: https://developer.apple.com/documentation/objectivec/1418956-nsobject/1418795-isequal?language=objc #[doc(alias = "isEqual:")] fn isEqual(&self, other: Option<&AnyObject>) -> bool where Self: Sized + Message,
{ unsafe { msg_send![self, isEqual: other] }
}
/// An integer that can be used as a table address in a hash table /// structure. /// /// Most objects that implement `NSObjectProtocol` also implements the /// [`Hash`][std::hash::Hash] trait, you likely want to use that instead. /// /// See [Apple's documentation][apple-doc] for details. /// /// [apple-doc]: https://developer.apple.com/documentation/objectivec/1418956-nsobject/1418859-hash?language=objc fn hash(&self) -> NSUInteger where Self: Sized + Message,
{ unsafe { msg_send![self, hash] }
}
/// Check if the object is an instance of the class, or one of its /// subclasses. /// /// See [`AnyObject::downcast_ref`] or [`Retained::downcast`] if your /// intention is to use this to cast an object to another, and see /// [Apple's documentation][apple-doc] for more details on what you may /// (and what you may not) do with this information in general. /// /// [apple-doc]: https://developer.apple.com/documentation/objectivec/1418956-nsobject/1418511-iskindofclass?language=objc #[doc(alias = "isKindOfClass:")] fn isKindOfClass(&self, cls: &AnyClass) -> bool where Self: Sized + Message,
{ unsafe { msg_send![self, isKindOfClass: cls] }
}
/// Check if the object is an instance of the class type, or one of its /// subclasses. /// /// See [`isKindOfClass`][Self::isKindOfClass] for details. #[deprecated = "use `isKindOfClass` directly, or cast your objects with `AnyObject::downcast_ref`"] // TODO: Use extern_protocol! once we get rid of this fn is_kind_of<T: ClassType>(&self) -> bool where Self: Sized + Message,
{ self.isKindOfClass(T::class())
}
/// Check if the object is an instance of a specific class, without /// checking subclasses. /// /// Note that this is rarely what you want, the specific class of an /// object is considered a private implementation detail. Use /// [`isKindOfClass`][Self::isKindOfClass] instead to check whether an /// object is an instance of a given class. /// /// See [Apple's documentation][apple-doc] for more details. /// /// [apple-doc]: https://developer.apple.com/documentation/objectivec/1418956-nsobject/1418766-ismemberofclass?language=objc #[doc(alias = "isMemberOfClass:")] fn isMemberOfClass(&self, cls: &AnyClass) -> bool where Self: Sized + Message,
{ unsafe { msg_send![self, isMemberOfClass: cls] }
}
/// Check whether the object implements or inherits a method with the /// given selector. /// /// See [Apple's documentation][apple-doc] for more details. /// /// If using this for availability checking, you might want to consider /// using the [`available!`] macro instead, as it is often more /// performant than this runtime check. /// /// [apple-doc]: https://developer.apple.com/documentation/objectivec/1418956-nsobject/1418583-respondstoselector?language=objc /// [`available!`]: crate::available #[doc(alias = "respondsToSelector:")] fn respondsToSelector(&self, aSelector: Sel) -> bool where Self: Sized + Message,
{ unsafe { msg_send![self, respondsToSelector: aSelector] }
}
/// Check whether the object conforms to a given protocol. /// /// See [Apple's documentation][apple-doc] for details. /// /// [apple-doc]: https://developer.apple.com/documentation/objectivec/nsobject/1418893-conformstoprotocol?language=objc #[doc(alias = "conformsToProtocol:")] fn conformsToProtocol(&self, aProtocol: &AnyProtocol) -> bool where Self: Sized + Message,
{ unsafe { msg_send![self, conformsToProtocol: aProtocol] }
}
/// A textual representation of the object. /// /// The returned class is `NSString`, but since that is defined in /// `objc2-foundation`, and `NSObjectProtocol` is defined in `objc2`, the /// declared return type is unfortunately restricted to be [`NSObject`]. /// It is always safe to cast the return value of this to `NSString`. /// /// You might want to use the [`Debug`][fmt::Debug] impl of the object /// instead, or if the object implements [`Display`][fmt::Display], the /// [`to_string`][std::string::ToString::to_string] method. /// /// /// # Example /// /// ``` /// use objc2::rc::Retained; /// # use objc2::runtime::{NSObjectProtocol, NSObject, NSObject as NSString}; /// # #[cfg(available_in_foundation)] /// use objc2_foundation::{NSObject, NSObjectProtocol, NSString}; /// /// # let obj = NSObject::new(); /// // SAFETY: Descriptions are always `NSString`. /// let desc: Retained<NSString> = unsafe { Retained::cast_unchecked(obj.description()) }; /// println!("{desc:?}"); /// ``` // // Only safe to override if the user-provided return type is NSString. fn description(&self) -> Retained<NSObject> where Self: Sized + Message,
{ unsafe { msg_send![self, description] }
}
/// A textual representation of the object to use when debugging. /// /// Like with [`description`][Self::description], the return type of this /// is always `NSString`. /// /// LLVM's po command uses this property to create a textual /// representation of the object. The default implementation returns the /// same value as `description`. Override either to provide custom object /// descriptions. // optional, introduced in macOS 10.8 // // Only safe to override if the user-provided return type is NSString. fn debugDescription(&self) -> Retained<NSObject> where Self: Sized + Message,
{ unsafe { msg_send![self, debugDescription] }
}
/// Check whether the receiver is a subclass of the `NSProxy` root class /// instead of the usual [`NSObject`]. /// /// See [Apple's documentation][apple-doc] for details. /// /// [apple-doc]: https://developer.apple.com/documentation/objectivec/1418956-nsobject/1418528-isproxy?language=objc /// /// /// # Example /// /// ``` /// use objc2::runtime::{NSObject, NSObjectProtocol}; /// /// let obj = NSObject::new(); /// assert!(!obj.isProxy()); /// ``` fn isProxy(&self) -> bool where Self: Sized + Message,
{ unsafe { msg_send![self, isProxy] }
}
/// The reference count of the object. /// /// This can rarely be useful when debugging memory management issues, /// though beware that in most real-world scenarios, your object may be /// retained by several autorelease pools, especially when debug /// assertions are enabled, so this value may not represent what you'd /// expect. /// /// /// # Example /// /// ``` /// use objc2::ClassType; /// use objc2::runtime::{NSObject, NSObjectProtocol}; /// /// let obj = NSObject::new(); /// assert_eq!(obj.retainCount(), 1); /// let obj2 = obj.clone(); /// assert_eq!(obj.retainCount(), 2); /// drop(obj2); /// assert_eq!(obj.retainCount(), 1); /// ``` fn retainCount(&self) -> NSUInteger where Self: Sized + Message,
{ unsafe { msg_send![self, retainCount] }
}
// retain, release and autorelease below to this protocol.
}
// SAFETY: Same as in extern_protocol! unsafeimpl<T> NSObjectProtocol for ProtocolObject<T> where T: ?Sized + NSObjectProtocol {} // SAFETY: Same as in extern_protocol! unsafeimpl ProtocolType fordyn NSObjectProtocol { const NAME: &'static str = "NSObject"; const __INNER: () = ();
} // SAFETY: Same as in extern_protocol! unsafeimpl<T> ImplementedBy<T> fordyn NSObjectProtocol where
T: ?Sized + Message + NSObjectProtocol,
{ const __INNER: () = ();
}
// SAFETY: Anything that implements `NSObjectProtocol` and is `Send` is valid // to convert to `ProtocolObject<dyn NSObjectProtocol + Send>`. unsafeimpl<T> ImplementedBy<T> fordyn NSObjectProtocol + Send where
T: ?Sized + Message + NSObjectProtocol + Send,
{ const __INNER: () = ();
}
// SAFETY: Anything that implements `NSObjectProtocol` and is `Sync` is valid // to convert to `ProtocolObject<dyn NSObjectProtocol + Sync>`. unsafeimpl<T> ImplementedBy<T> fordyn NSObjectProtocol + Sync where
T: ?Sized + Message + NSObjectProtocol + Sync,
{ const __INNER: () = ();
}
// SAFETY: Anything that implements `NSObjectProtocol` and is `Send + Sync` is // valid to convert to `ProtocolObject<dyn NSObjectProtocol + Send + Sync>`. unsafeimpl<T> ImplementedBy<T> fordyn NSObjectProtocol + Send + Sync where
T: ?Sized + Message + NSObjectProtocol + Send + Sync,
{ const __INNER: () = ();
}
extern_conformance!( unsafeimpl NSObjectProtocol for NSObject {}
);
#[allow(non_snake_case)] // Follow the naming scheme in framework crates impl NSObject {
extern_methods!( /// Create a new empty `NSObject`. /// /// This method is a shorthand for calling [`alloc`][AnyThread::alloc] /// and then [`init`][Self::init]. #[unsafe(method(new))] #[unsafe(method_family = new)] pubfn new() -> Retained<Self>;
/// Initialize an already allocated object. /// /// See [Apple's documentation][apple-doc] for details. /// /// [apple-doc]: https://developer.apple.com/documentation/objectivec/nsobject/1418641-init?language=objc /// /// /// # Example /// /// ``` /// use objc2::runtime::NSObject; /// use objc2::AnyThread; /// /// let obj = NSObject::init(NSObject::alloc()); /// ``` #[unsafe(method(init))] #[unsafe(method_family = init)] pubfn init(this: Allocated<Self>) -> Retained<Self>;
/// Objective-C equality has approximately the same semantics as Rust /// equality (although less aptly specified). /// /// At the very least, equality is _expected_ to be symmetric and /// transitive, and that's about the best we can do. /// /// See also <https://nshipster.com/equality/> impl PartialEq for NSObject { #[inline] #[doc(alias = "isEqual:")] fn eq(&self, other: &Self) -> bool { self.isEqual(Some(other))
}
}
/// Most types' equality is reflexive. impl Eq for NSObject {}
/// Hashing in Objective-C has the exact same requirement as in Rust: /// /// > If two objects are equal (as determined by the isEqual: method), /// > they must have the same hash value. /// /// See <https://developer.apple.com/documentation/objectivec/1418956-nsobject/1418859-hash> impl hash::Hash for NSObject { #[inline] fn hash<H: hash::Hasher>(&self, state: &mut H) {
<Selfas NSObjectProtocol>::hash(self).hash(state);
}
}
// Ensure that importing `NSObjectProtocol::hash` does not cause conflicts // when using `Hash::hash` on normal types. mod hash_does_not_overlap_with_normal_hash_method { #[allow(unused_imports)] usecrate::runtime::NSObjectProtocol; use std::collections::hash_map::DefaultHasher; use std::hash::Hash;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.