Macro objc2::extern_class
source · macro_rules! extern_class { ( $(#[$m:meta])* $v:vis struct $name:ident; unsafe impl ClassType for $for:ty { $(#[inherits($($inheritance_rest:ty),+)])? type Super = $superclass:ty; } ) => { ... }; ( $(#[$m:meta])* $v:vis struct $name:ident { $($field_vis:vis $field:ident: $field_ty:ty,)* } unsafe impl ClassType for $for:ty { $(#[inherits($($inheritance_rest:ty),+)])? type Super = $superclass:ty; } ) => { ... }; }
Expand description
Create a new type to represent an Objective-C class.
This is similar to an @interface
declaration in Objective-C.
The given struct name should correspond to a valid Objective-C class,
whose instances have the encoding Encoding::Object
. (as an example:
NSAutoreleasePool
does not have this!)
You must specify the superclass of this class, similar to how you would in Objective-C.
Due to Rust trait limitations, specifying e.g. the superclass NSData
would not give you easy access to NSObject
’s functionality. Therefore,
you may specify additional parts of the inheritance chain using the
#[inherits(...)]
attribute.
Specification
The syntax is similar enough to Rust syntax that if you invoke the macro
with parentheses (as opposed to curly brackets), rustfmt
will be able to
format the contents.
This creates an opaque struct containing the superclass (which means that auto traits are inherited from the superclass), and implements the following traits for it to allow easier usage as an Objective-C object:
RefEncode
Message
ClassType
Deref<Target = $superclass>
DerefMut
AsRef<$inheritance_chain>
AsMut<$inheritance_chain>
Borrow<$inheritance_chain>
BorrowMut<$inheritance_chain>
The macro allows specifying fields on the struct, but only zero-sized
types like PhantomData
and declare::Ivar
are allowed here!
Safety
The specified superclass must be correct. The object must also respond to
standard memory management messages (this is upheld if NSObject
is
part of its inheritance chain).
Examples
Create a new type to represent the NSFormatter
class.
use objc2::foundation::NSObject;
use objc2::rc::{Id, Shared};
use objc2::{ClassType, extern_class, msg_send_id};
extern_class!(
/// An example description.
#[derive(PartialEq, Eq, Hash)] // Uses the superclass' implementation
// Specify the class and struct name to be used
pub struct NSFormatter;
// Specify the superclass, in this case `NSObject`
unsafe impl ClassType for NSFormatter {
type Super = NSObject;
}
);
// Provided by the implementation of `ClassType`
let cls = NSFormatter::class();
// `NSFormatter` implements `Message`:
let obj: Id<NSFormatter, Shared> = unsafe { msg_send_id![cls, new] };
Represent the NSDateFormatter
class, using the NSFormatter
type we
declared previously to specify as its superclass.
use objc2::foundation::NSObject;
use objc2::{extern_class, ClassType};
extern_class!(
#[derive(PartialEq, Eq, Hash)]
pub struct NSDateFormatter;
unsafe impl ClassType for NSDateFormatter {
// Specify the correct inheritance chain
#[inherits(NSObject)]
type Super = NSFormatter;
}
);
See the source code of objc2::foundation
in general for more examples.